Lay András
Lay András

Reputation: 845

Elasticsearch no result with multi_match

I have the following mappings with Elasticsearch 7.10:

PUT /test
{
    "settings": {
        "analysis": {
            "analyzer": {
                "ekezet": {
                    "type": "custom",
                    "tokenizer": "standard",
                    "filter": [
                        "lowercase",
                        "asciifolding"
                    ]
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "email": {
                "type": "text"
            },
            "name": {
                "type": "text",
                "analyzer": "ekezet"
            }
        }
    }
}

Data:

POST /test/_doc/1
{
    "email": "[email protected]",
    "name": "lufi"
}

Query:

POST /test/_search
{
    "query": {
        "bool": {
            "must": {
                "multi_match": {
                    "type": "cross_fields",
                    "query": "[email protected] lufi",
                    "fields": [
                        "email",
                        "name"
                    ],
                    "operator": "and"
                }
            }
        }
    }
}

Both "[email protected]" and "lufi" exists in the same document, but no result. Why?

If the query is only "[email protected]" or "lufi" there is a result.

Upvotes: 1

Views: 384

Answers (1)

Bhavya
Bhavya

Reputation: 16172

The and operator signifies that all terms must be present in a single field for a document to match

Please refer to this ES official documentation, to know more about cross_fields

and is executed as:

+(email:[email protected]  name:[email protected])
+(email:lufi  name:lufi)

You need to use the operator or here

{
  "query": {
    "bool": {
      "must": {
        "multi_match": {
          "type": "cross_fields",
          "query": "[email protected] lufi",
          "fields": [
            "email",
            "name"
          ],
          "operator": "or"
        }
      }
    }
  }
}

Search Result:

 "hits": [
      {
        "_index": "65006888",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.5753642,
        "_source": {
          "email": "[email protected]",
          "name": "lufi"
        }
      }
    ]

You can even use the minimum_should_match parameter that will indicate here that either [email protected] or lufi must be present in either of the email or name fields

{
  "query": {
    "bool": {
      "must": {
        "multi_match": {
          "type": "cross_fields",
          "query": "[email protected] lufi",
          "fields": [
            "email",
            "name"
          ],
          "minimum_should_match": "50%"
        }
      }
    }
  }
}

Edit 1:

The cross_field type can only work in term-centric mode on fields that have the same analyzer as mentioned in the documentation

So, if you change your index mapping like this:

{
  "settings": {
    "analysis": {
      "analyzer": {
        "ekezet": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "email": {
        "type": "text",
        "analyzer":"ekezet"     <-- note this
      },
      "name": {
        "type": "text",
        "analyzer": "ekezet"
      }
    }
  }
}

With the above index mapping, the search query given in the question works fine.

Upvotes: 2

Related Questions