30/08/2017 - ELASTICSEARCH
Examples below are based on elasticsearch version 1.7 so depending on your version, you might or might not be able run certain queries. If your query fails, you can validate with query below which will tell you what's wrong with it.
curl -XGET '127.0.0.1:9200/product_test/_validate/query?explain=true&pretty=1' -d '
{
your query goes here
}'
Elasticsearch has a single set of components called queries which can have endless combinations. Components can be used in "filtering" context and "query" context as explained below. For more information, visit Queries and Filters.
_score
(relevance).In general, a filtering (non-scoring) query will outperform a scoring query.
General rule: Use "scoring queries" for full-text or relevance dependant queries otherwise use "filtering (non-scoring) queries" for everything else.
There are many different queries for us to use but some of them used more often than others. List below includes the most important queries. For more information, visit Most Important Queries.
This query returns all documents.
# Give me all documents.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"match_all": {}
}
}'
This is used 99% of times if you want a full-text or exact value search.
# Give me documents where "Product1" keyword found in "name" mapping.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"match": {
"name": "Product1" # Full-text (analyzed) field
}
}
}'
# Give me documents where "id" mapping equals to "1".
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"match": {
"id": 1 # Exact-value (not_analyzed) field
}
}
}'
Tip: For exact-value searches, you should use filter
instead of query
because filter
is cached.
This is same as match
but used to query more than one field. It behaves like OR
condition.
# Give me documents as long as "Product1" keyword is found either in "name" or "shops.name" mappings.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"multi_match": {
"query": "Product1",
"fields": [
"name", # Full-text (analyzed) field
"shops.name" # Exact-value (not_analyzed) field
]
}
}
}'
It is used for finding numbers or dates which satisfies the given condition. The conditions are:
gt
: Greater thangte
: Greater than or equal tolt
: Less thanlte
: Less than or equal to# Give me documents where "id" mapping equals to "4/5/6".
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"range": {
"id": {
"gte": 4,
"lt": 7
}
}
}
}'
This is used to search by exact values such as numbers, dates, booleans or not_analyzed
exact-value string fields so this is not used for full-text searches.
# Give me documents where "shops.name" mapping equals to "Shop7".
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"term": {
"shops.name": "Shop7" # Exact-value (not_analyzed) field
}
}
}'
# Give me only searchable documents.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"term": {
"is_searchable": true # Exact-value (not_analyzed) field
}
}
}'
This is same as term
but used to query more than one keywords in a single field. It behaves like OR
condition.
# Give me documents as long as "Shop4" or "Shop7" keywords are found "shops.name" mapping.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"terms": {
"shops.name": ["Shop4", "Shop7"] # Exact-value (not_analyzed) field
}
}
}'
# Give me documents where IDs equal to "4" or "7" in "id" mapping.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"terms": {
"id": [4, 7] # Exact-value (not_analyzed) field
}
}
}'
This is used to find documents if the "mapping" doesn't contain any data. It is same as field = ''
or field IS NULL
.
# Give me documents where "name" mapping hasNULL
or no data in it.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"filtered": {
"filter": {
"missing": {
"field": "name"
}
}
}
}
}'
This is used to find documents if the "mapping" does contain data. It is same as field <> ''
or field IS NOT NULL
.
# Give me documents where "name" mapping has data in it.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"filtered": {
"filter": {
"exists": {
"field": "name"
}
}
}
}
}'
To combine multiple queries into a single query, you should use bool
query which accepts the following parameters. For more information, visit Combining queries.
must
: Clauses that must match for the document to be included.must_not
: Clauses that must not match for the document to be included.should
: If the clauses match, they increase the _score
otherwise, they have no effect. Main aim is to manipulate document relevance so it is a "scoring" query.filter
: If the clauses match, document is included otherwise excluded. This has no affect on _score
nor relevance so it is a "non-scoring" query.Example query below must satisfy 2 conditions in order to include or exclude documents. On top of that there are 2 rules which will value certain documents more than the others. Read the comments below.
curl -XPOST '127.0.0.1:9200/product_test/_search?pretty' -d '
{
"query": {
"bool": {
"must": {
"match": {
"name": "Product" # Make sure document "name" contains "Product" keyword. Include.
}
},
"must_not": {
"match": {
"name": "Product1" # Make sure document "name" does not contain "Product1" keyword. Exclude.
}
},
"should": [
{
"match": {
"id": 7 # If document "id" equals to "1" then score it higher so it appears higher. Scoring.
}
},
{
"range": {
"year": {
"gt": "2014" # If document "year" greater than "2014" then score them higher so they appear higher. Scoring.
}
}
}
]
}
}
}'
Note: If there are no must
clauses, at least one should
clause has to match. However, if there is at least one must
clause, no should
clauses are required to match.
Opposed to logic above, if you don't want to increase the value of documents based on their "year" then you will just filter them instead. By moving range
into filter
clause, it becomes "non-scoring" query so as a result performance increases too.