Term-level queries

Term-level queries search an index for documents that contain an exact search term. Documents returned by a term-level query are not sorted by their relevance scores.

When working with text data, use term-level queries for fields mapped as keyword only.

Term-level queries are not suited for searching analyzed text fields. To return analyzed fields, use a full-text query.

Term-level query types

The following table lists all term-level query types.

Query typeDescription
termSearches for documents with an exact term in a specific field.
termsSearches for documents with one or more terms in a specific field.
terms_setSearches for documents that match a minimum number of terms in a specific field.
idsSearches for documents by document ID.
rangeSearches for documents with field values in a specific range.
prefixSearches for documents with terms that begin with a specific prefix.
existsSearches for documents with any indexed value in a specific field.
fuzzySearches for documents with terms that are similar to the search term within the maximum allowed Levenshtein distance. The Levenshtein distance measures the number of one-character changes needed to change one term to another term.
wildcardSearches for documents with terms that match a wildcard pattern.
regexpSearches for documents with terms that match a regular expression.

Term

Use the term query to search for an exact term in a field.

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "term": {
  5. "line_id": {
  6. "value": "61809"
  7. }
  8. }
  9. }
  10. }

copy

Terms

Use the terms query to search for multiple terms in the same field.

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "terms": {
  5. "line_id": [
  6. "61809",
  7. "61810"
  8. ]
  9. }
  10. }
  11. }

copy

You get back documents that match any of the terms.

Terms set

With a terms set query, you can search for documents that match a minimum number of exact terms in a specified field. The terms_set query is similar to the terms query, but you can specify the minimum number of matching terms that are required to return a document. You can specify this number either in a field in the index or with a script.

As an example, consider an index that contains students with classes they have taken. When setting up the mapping for this index, you need to provide a numeric field that specifies the minimum number of matching terms that are required to return a document:

  1. PUT students
  2. {
  3. "mappings": {
  4. "properties": {
  5. "name": {
  6. "type": "keyword"
  7. },
  8. "classes": {
  9. "type": "keyword"
  10. },
  11. "min_required": {
  12. "type": "integer"
  13. }
  14. }
  15. }
  16. }

copy

Next, index two documents that correspond to students:

  1. PUT students/_doc/1
  2. {
  3. "name": "Mary Major",
  4. "classes": [ "CS101", "CS102", "MATH101" ],
  5. "min_required": 2
  6. }

copy

  1. PUT students/_doc/2
  2. {
  3. "name": "John Doe",
  4. "classes": [ "CS101", "MATH101", "ENG101" ],
  5. "min_required": 2
  6. }

copy

Now search for students who have taken at least two of the following classes: CS101, CS102, MATH101:

  1. GET students/_search
  2. {
  3. "query": {
  4. "terms_set": {
  5. "classes": {
  6. "terms": [ "CS101", "CS102", "MATH101" ],
  7. "minimum_should_match_field": "min_required"
  8. }
  9. }
  10. }
  11. }

copy

The response contains both students:

  1. {
  2. "took" : 44,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 2,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 1.4544616,
  16. "hits" : [
  17. {
  18. "_index" : "students",
  19. "_id" : "1",
  20. "_score" : 1.4544616,
  21. "_source" : {
  22. "name" : "Mary Major",
  23. "classes" : [
  24. "CS101",
  25. "CS102",
  26. "MATH101"
  27. ],
  28. "min_required" : 2
  29. }
  30. },
  31. {
  32. "_index" : "students",
  33. "_id" : "2",
  34. "_score" : 0.5013843,
  35. "_source" : {
  36. "name" : "John Doe",
  37. "classes" : [
  38. "CS101",
  39. "MATH101",
  40. "ENG101"
  41. ],
  42. "min_required" : 2
  43. }
  44. }
  45. ]
  46. }
  47. }

To specify the minimum number of terms a document should match with a script, provide the script in the minimum_should_match_script field:

  1. GET students/_search
  2. {
  3. "query": {
  4. "terms_set": {
  5. "classes": {
  6. "terms": [ "CS101", "CS102", "MATH101" ],
  7. "minimum_should_match_script": {
  8. "source": "Math.min(params.num_terms, doc['min_required'].value)"
  9. }
  10. }
  11. }
  12. }
  13. }

copy

IDs

Use the ids query to search for one or more document ID values.

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "ids": {
  5. "values": [
  6. 34229,
  7. 91296
  8. ]
  9. }
  10. }
  11. }

copy

Range

You can search for a range of values in a field with the range query.

To search for documents where the line_id value is >= 10 and <= 20:

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "range": {
  5. "line_id": {
  6. "gte": 10,
  7. "lte": 20
  8. }
  9. }
  10. }
  11. }

copy

ParameterBehavior
gteGreater than or equal to.
gtGreater than.
lteLess than or equal to.
ltLess than.

In addition to the range query parameters, you can provide date formats or relation operators such as “contains” or “within.” To see the supported field types for range queries, see Range query optional parameters. To see all date formats, see Formats.

Assume that you have a products index and you want to find all the products that were added in the year 2019:

  1. GET products/_search
  2. {
  3. "query": {
  4. "range": {
  5. "created": {
  6. "gte": "2019/01/01",
  7. "lte": "2019/12/31"
  8. }
  9. }
  10. }
  11. }

copy

Specify relative dates by using date math.

To subtract 1 year and 1 day from the specified date, use the following query:

  1. GET products/_search
  2. {
  3. "query": {
  4. "range": {
  5. "created": {
  6. "gte": "2019/01/01||-1y-1d"
  7. }
  8. }
  9. }
  10. }

copy

The first date that we specify is the anchor date or the starting point for the date math. Add two trailing pipe symbols. You could then add one day (+1d) or subtract two weeks (-2w). This math expression is relative to the anchor date that you specify.

You could also round off dates by adding a forward slash to the date or time unit.

To find products added in the last year and rounded off by month:

  1. GET products/_search
  2. {
  3. "query": {
  4. "range": {
  5. "created": {
  6. "gte": "now-1y/M"
  7. }
  8. }
  9. }
  10. }

copy

The keyword now refers to the current date and time.

Prefix

Use the prefix query to search for terms that begin with a specific prefix.

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "prefix": {
  5. "speaker": "KING"
  6. }
  7. }
  8. }

copy

Exists

Use the exists query to search for documents that contain a specific field.

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "exists": {
  5. "field": "speaker"
  6. }
  7. }
  8. }

copy

Fuzzy

A fuzzy query searches for documents with terms that are similar to the search term within the maximum allowed Levenshtein distance. The Levenshtein distance measures the number of one-character changes needed to change one term to another term. These changes include:

  • Replacements: cat to bat
  • Insertions: cat to cats
  • Deletions: cat to at
  • Transpositions: cat to act

A fuzzy query creates a list of all possible expansions of the search term that fall within the Levenshtein distance. You can specify the maximum number of such expansions in the max_expansions field. Then is searches for documents that match any of the expansions.

The following example query searches for the speaker HALET (misspelled HAMLET). The maximum edit distance is not specified, so the default AUTO edit distance is used:

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "fuzzy": {
  5. "speaker": {
  6. "value": "HALET"
  7. }
  8. }
  9. }
  10. }

copy

The response contains all documents where HAMLET is the speaker.

The following example query searches for the word cat with advanced parameters:

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "fuzzy": {
  5. "speaker": {
  6. "value": "HALET",
  7. "fuzziness": "2",
  8. "max_expansions": 40,
  9. "prefix_length": 0,
  10. "transpositions": true,
  11. "rewrite": "constant_score"
  12. }
  13. }
  14. }
  15. }

copy

Wildcard

Use wildcard queries to search for terms that match a wildcard pattern.

FeatureBehavior
*Specifies all valid values.
?Specifies a single valid value.

To search for terms that start with H and end with Y:

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "wildcard": {
  5. "speaker": {
  6. "value": "H*Y"
  7. }
  8. }
  9. }
  10. }

copy

If we change * to ?, we get no matches, because ? refers to a single character.

Wildcard queries tend to be slow because they need to iterate over a lot of terms. Avoid placing wildcard characters at the beginning of a query because it could be a very expensive operation in terms of both resources and time.

Regexp

Use the regexp query to search for terms that match a regular expression.

This regular expression matches any single uppercase or lowercase letter:

  1. GET shakespeare/_search
  2. {
  3. "query": {
  4. "regexp": {
  5. "play_name": "[a-zA-Z]amlet"
  6. }
  7. }
  8. }

copy

A few important notes:

  • Regular expressions are applied to the terms in the field (i.e. tokens), not the entire field.
  • Regular expressions use the Lucene syntax, which differs from more standardized implementations. Test thoroughly to ensure that you receive the results you expect. To learn more, see the Lucene documentation.
  • regexp queries can be expensive operations and require the search.allow_expensive_queries setting to be set to true. Before making frequent regexp queries, test their impact on cluster performance and examine alternative queries for achieving similar results.