Reputation: 845
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
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