Is there different between multiple `match` with single term in `should` vs a single `match` with multiple term in `should`?

Viewed 36

Is there differences between the 2 below?

GET books/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "description": {
              "query": "cat dog"
            }
          }
        }       
      ]
    }
  }
}

and

GET books/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "description": {
              "query": "cat"
            }
          }
        },
        {
          "match": {
            "description": {
              "query": "dog"
            }
          }
        }       
      ]
    }
  }
}

From the results I see them as identical. The index document I use is as below

POST books/_bulk
{"index":{}}
{ "title": "Dogs", "description": "A fox jump over the lazy dog" }
{"index":{}}
{ "title": "Cats", "description": "Garfield the sleepy cat" }
{"index":{}}
{ "title": "Sleepy", "description": "Rest is important" }
{"index":{}}
{ "title": "Rich", "description": "Money is never enough" }
{"index":{}}
{ "title": "Pets", "description": "Dog and cat are friends" }
{"index":{}}
{ "title": "Character", "description": "Are you really a dog person?" }

The mapping is the default mapping

{
  "books" : {
    "mappings" : {
      "properties" : {
        "description" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}
1 Answers

it depends what analyzer your description field is using, if you are using the standard or whitespace analyzer which breaks the text on whitespace, it will be same.

You can use the Explain API to inspect what search time tokens is generated for your search term.

You should also note that default operator of match query is OR and as explained in the same offical doc

operator (Optional, string) Boolean logic used to interpret text in the query value. Valid values are:

OR (Default) For example, a query value of capital of Hungary is interpreted as capital OR of OR Hungary.

AND For example, a query value of capital of Hungary is interpreted as capital AND of AND Hungary.

When default analyzer ie standard used on text field, explain API returns below for search query

POST /{your-index}/_search?explain=true

{
    "query": {
        "bool": {
            "should": [
                {
                    "match": {
                        "description": {
                            "query": "cat dog"
                        }
                    }
                }
            ]
        }
    }
}

And search query with explain param

 "_explanation": {
                    "value": 0.6931471,
                    "description": "sum of:",
                    "details": [
                        {
                            "value": 0.6931471,
                            "description": "weight(description:cat in 0) [PerFieldSimilarity], result of:",
                            "details": [
                                {
                                    "value": 0.6931471,
                                    "description": "score(freq=1.0), computed as boost * idf * tf from:",
                                    "details": [
                                        {
                                            "value": 2.2,
                                            "description": "boost",
                                            "details": []
                                        },
                                        {
                                            "value": 0.6931472,
                                            "description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                                            "details": [
                                                {
                                                    "value": 1,
                                                    "description": "n, number of documents containing term",
                                                    "details": []
                                                },
                                                {
                                                    "value": 2,
                                                    "description": "N, total number of documents with field",
                                                    "details": []
                                                }
                                            ]
                                        },
                                        {
                                            "value": 0.45454544,
                                            "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                                            "details": [
                                                {
                                                    "value": 1.0,
                                                    "description": "freq, occurrences of term within document",
                                                    "details": []
                                                },
                                                {
                                                    "value": 1.2,
                                                    "description": "k1, term saturation parameter",
                                                    "details": []
                                                },
                                                {
                                                    "value": 0.75,
                                                    "description": "b, length normalization parameter",
                                                    "details": []
                                                },
                                                {
                                                    "value": 4.0,
                                                    "description": "dl, length of field",
                                                    "details": []
                                                },
                                                {
                                                    "value": 4.0,
                                                    "description": "avgdl, average length of field",
                                                    "details": []
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            },
            {
                "_shard": "[66329708][0]",
                "_node": "tMk7cyaBRSeJ8dxuSQdHRg",
                "_index": "66329708",
                "_type": "_doc",
                "_id": "3",
                "_score": 0.6931471,
                "_source": {
                    "description": "Garfield the sleepy dog"
                },
                "_explanation": {
                    "value": 0.6931471,
                    "description": "sum of:",
                    "details": [
                        {
                            "value": 0.6931471,
                            "description": "weight(description:dog in 0) [PerFieldSimilarity], result of:",
                            "details": [
                                {
                                    "value": 0.6931471,
                                    "description": "score(freq=1.0), computed as boost * idf * tf from:",
                                    "details": [
                                        {
                                            "value": 2.2,
                                            "description": "boost",
                                            "details": []
                                        },
                                        {
                                            "value": 0.6931472,
                                            "description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                                            "details": [
                                                {
                                                    "value": 1,
                                                    "description": "n, number of documents containing term",
                                                    "details": []
                                                },
                                                {
                                                    "value": 2,
                                                    "description": "N, total number of documents with field",
                                                    "details": []
                                                }
                                            ]
                                        },
                                        {
                                            "value": 0.45454544,
                                            "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                                            "details": [
                                                {
                                                    "value": 1.0,
                                                    "description": "freq, occurrences of term within document",
                                                    "details": []
                                                },
                                                {
                                                    "value": 1.2,
                                                    "description": "k1, term saturation parameter",
                                                    "details": []
                                                },
                                                {
                                                    "value": 0.75,
                                                    "description": "b, length normalization parameter",
                                                    "details": []
                                                },
                                                {
                                                    "value": 4.0,
                                                    "description": "dl, length of field",
                                                    "details": []
                                                },
                                                {
                                                    "value": 4.0,
                                                    "description": "avgdl, average length of field",
                                                    "details": []
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }

You can note that search terms used to search is cat and dog.

While if you use different analyzer like keyword analyzer and index mapping like below

{
    "mappings": {
        "properties": {
            "description": {
                "type": "text",
                "analyzer": "keyword" // Note this
            }
        }
    }
}

Index sample data

{
    "description" : "cat dog"
}

{
    "description" : "Garfield the sleepy dog"
}

And make below search call

{
    "query": {
        "bool": {
            "should": [
                {
                    "match": {
                        "description": {
                            "query": "cat dog"
                        }
                    }
                }
            ]
        }
    }
}

You will notice in explain API below tokens are used to search

"weight(description:cat dog in 0) [PerFieldSimilarity], result of:", As you can see now cat and dog is not split as match query uses the same analyzer applied at index time which uses keyword analyzer in example and doesn't break tokens on whitespace.

Related