0
votes

I am learning elasticsearch-7.4.0 and working with basic queries.

I have a product index which has a field name with the following mapping:

"name" : {
  "type" : "text",
  "fields" : {
    "keyword" : {
      "type" : "keyword",
      "ignore_above" : 256
    }
  }
}

When I am executing the term query to match documents with name "Wine - Ice Wine".

GET /product/_search
{
  "from": 0,
  "size" : 1000,
  "query": {
    "term": {
      "name": {
        "value": "Wine - Ice Wine"
      }
    }
  }
}

The output I am getting:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

When I am running match query:

GET /product/_search
{
  "from": 0,
  "size" : 1000,
  "query": {
    "match": {
      "name": "Wine - Ice Wine"
    }
  }
}

The output I am getting:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 75,
      "relation" : "eq"
    },
    "max_score" : 12.354952,
    "hits" : [
      {
        "_index" : "product",
        "_type" : "doc",
        "_id" : "403",
        "_score" : 12.354952,
        "_source" : {
          "name" : "Wine - Ice Wine",
          "price" : 127,
          "in_stock" : 26,
          "sold" : 334,
          "tags" : [
            "Alcohol",
            "Wine"
          ],
          "description" : "Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh. Quisque id justo sit amet sapien dignissim vestibulum.",
          "is_active" : true,
          "created" : "2010/04/12"
        }
      }
    ]
  }
}

As mentioned, term level queries look for exact match.
So, I am specifying the entire string in the search query.
Both the queries should return the same results.

1

1 Answers

3
votes

Term queries are to be used on keyword fields in order to get the exact match.

From the above link, we have the below for keyword datatype:

They are typically used for filtering (Find me all blog posts where status is published), for sorting, and for aggregations. Keyword fields are only searchable by their exact value.

From your mapping, the field name has sibling field which is name.keyword which is of type keyword.

Modify your term query to make use of it as below and it would give you the desired result.

GET /product/_search
{
  "from": 0,
  "size" : 1000,
  "query": {
    "term": {
      "name.keyword": {                  <---- Note this
        "value": "Wine - Ice Wine"
      }
    }
  }
}

While on the other hand, the match query you make use of on text field goes through the Analysis phase.

Basically when you have a field of text type and when you ingest a document it converts the sentences into tokens, converts them into small case letters and thereby stores in the inverted index. This would be index time analysis

The same thing happens when you use a match query i.e. whatever you add in the query part, it breaks down into individual words or tokens and searches them in inverted index. This is search time analysis.

The analysis is done by concept called Analyzers. By default it makes use of Standard Analyzer.

I'd suggest you go through the links to understand more on this.

Hope this helps!