1

I am using ES 7.10.2

I have fields with keyword and text mappings.

When user specifies the search string, I wanted to parse the pieces of search string, then match each of those piece to each specific field, in the specific way that field mapping is configured, such that using same analyzer get used by search query as provided in field mapping.

For this requirement I am using Query-String-Query, I validated the above statement using _validate query.

But the same is also seems to be true, regarding Multi_Match query.

See below example:

POST /testindex/_doc/1
{"id":1,"firstname":"john","middlename":"clark","lastname":"smith"}

POST /testindex/_doc/2
{"id":2,"firstname":"john","middlename":"paladini","lastname":"miranda"}

Now When I use validate query for both Multi_Match and Query_String_Query

GET testindex/_validate/query?pretty=true&explain=true
{
   "query": {
     "multi_match" : {
      "operator" : "or",
      "fields" : [
         "firstname",
         "lastname",
         "firstname.keyword",
         "lastname.keyword"
      ],
      "query" : "john smith"
   }
   }
}

GET testindex/_validate/query?pretty=true&explain=true
{
   "query": {
    "query_string": {
      "default_operator": "OR",
      "fields" : [
         "firstname",
         "lastname",
         "firstname.keyword",
         "lastname.keyword"
      ],
      "query" : "john smith"
    }
   }
}

Both of them produce the exact same explanation:

{
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "valid" : true,
  "explanations" : [
    {
      "index" : "testindex",
      "valid" : true,
      "explanation" : "((firstname:john firstname:smith) | firstname.keyword:john smith | lastname.keyword:john smith | (lastname:john lastname:smith))"
    }
  ]
}

I know that QSQ is sensitive to invalid syntax.

Then what can be the difference between Multi_Match and QSQ ? are there any performace consideration ? and though multi_match is based on match it seems to behave fine with keyword field also?

Nishikant Tayade
  • 483
  • 3
  • 12

1 Answers1

1

Very good question, first multi_match is not just based on text field, it works on the keyword field as well, it simply applied the same analyzer on search terms which was used index time(unless search time analyzer is defined), In case of keyword field, default keyword analyzer is used(no-op analyzer), hence it doesn't break the query terms.

Also query_string also uses the same analyzer on query term which is used at the index time, but it allows to use the operator like OR and AND in the query term, while in multi_match these operator is considered as part of query terms, Hence they work differently when you use these operators.

Example:

{
   "query": {
    "query_string": {
      "fields" : [
         "firstname",
         "lastname"
      ],
      "query" : "john OR smith"
    }
   }
}

returns below query explaination

"(lastname:john | firstname:john) (firstname:smith | lastname:smith)" (Note, it removed OR and considered it as an operator).

Again, if you use that OR in the multi_match query

{
    "query": {
        "multi_match": {
            "operator": "OR",
            "fields": [
                "firstname",
                "lastname"
            ],
            "query": "john OR smith"
        }
    }
}

it generates different, explanation

(lastname:john OR smith | firstname:john OR smith)

You can index, below document, considering firstname and lastname is a keyword field.

{
    "mappings": {
        "properties": {
            "firstname": {
                "type": "keyword"
            },
            "lastname": {
                "type": "keyword"
            }
        }
    }
}

Index sample docs

{
    "firstname": "john smith",
    "lastname": "smith"
}

And searching for john OR smith in both fields, will return nothing

{
    "query": {
        "multi_match": {
            "fields": [
                "firstname",
                "lastname"
            ],
            "query": "john OR smith"
        }
    }
}

But in query string it will return document, as lastname has smith

{
   "query": {
    "query_string": {
      "fields" : [
         "firstname",
         "lastname"
      ],
      "query" : "john OR smith"
    }
   }
}
Amit
  • 30,756
  • 6
  • 57
  • 88
  • If you want to use the operator logic, which is supported in `query_string`, you need to use the `boolean query` as explained in my recent answer https://stackoverflow.com/a/71367457/4039431 please take a look to uderstand more difference in query string and multi_match. – Amit Mar 06 '22 at 05:28
  • Thanks for the detailed response! I was reading about the queries and found the statements : **multi_match (with operator and) will make sure that ALL terms exist in at least one field While query_string (with default_operator AND) will check that EACH term exists in at least one field**, given in answer of this [question](https://stackoverflow.com/questions/15423033/multi-field-multi-word-match-without-query-string) – Nishikant Tayade Mar 06 '22 at 06:19
  • But this doesn't seem to be true, because even if "AND" operator in both QSQ and MMQ, their explanation obtained from validate query response is exactly the same, is this right? – Nishikant Tayade Mar 06 '22 at 06:21