I have an ES 6.5 index with the following mappings -
{
"hotel": {
"mappings": {
"hotel": {
"properties": {
"hotelAmenities": {
"type": "nested",
"properties": {
"enabled": {
"type": "boolean"
},
"featured": {
"type": "boolean"
},
"key": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"hotelStatus": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"verbatim": {
"type": "keyword"
}
},
"analyzer": "english"
}
}
}
}
}
}
Sample document -
{
"name": "Hotel with amenities",
"hotelStatus": "BOOKABLE",
"hotelAmenities": [
{
"key": "POOL",
"name": "Pool",
"enabled": true,
"featured": true
},
{
"key": "LAUNDRY",
"name": "Laundry",
"enabled": true,
"featured": true
}
]
}
I am using a nested query to target the hotelAmenities field, and the intent is to have an AND relationship (the hotel has POOL and LAUNDRY amenity), but it only works when there is a single nested field searched.
{
"from": 0,
"size": 200,
"query": {
"bool": {
"must": [
{
"nested": {
"query": {
"bool": {
"must": [
// ONLY 1 works here
{
"match": {
"hotelAmenities.name": "laundry"
}
},
{
"match": {
"hotelAmenities.name": "pool"
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"path": "hotelAmenities",
"ignore_unmapped": false,
"score_mode": "max",
"boost": 1.0
}
}
],
"must_not": [
{
"match": {
"hotelStatus": {
"query": "DECOMMISSIONED",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"post_filter": {
"geo_distance": {
...
}
},
"version": true
}
I also tried with a query
approach on the nested fields like this, and it exhibits the same behavior where only one nested amenity can be searched.
{
"from": 0,
"size": 200,
"query": {
"bool": {
"must": [
{
"nested": {
"query": {
"bool": {
"must": [
// ONLY 1 works here
{
"match": {
"hotelAmenities.name": {
"query": "laundry",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
},
{
"match": {
"hotelAmenities.name": {
"query": "pool",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"path": "hotelAmenities",
"ignore_unmapped": false,
"score_mode": "max",
"boost": 1.0
}
}
],
"must_not": [
{
"match": {
"hotelStatus": {
"query": "DECOMMISSIONED",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"post_filter": {
"geo_distance": {
...
}
},
"version": true
}
If I remove one or the other in my example then the documents are found correctly. What could the cause of this be?
Each nested element is stored in its own internal document, so if you have several constraints on those elements, you need one nested query per constraint, as shown below:
"query": {
"bool": {
"must": [
{
"nested": {
"query": {
"match": {
"hotelAmenities.name": "laundry"
}
},
"path": "hotelAmenities",
"ignore_unmapped": false,
"score_mode": "max",
"boost": 1
}
},
{
"nested": {
"query": {
"match": {
"hotelAmenities.name": "pool"
}
},
"path": "hotelAmenities",
"ignore_unmapped": false,
"score_mode": "max",
"boost": 1
}
}
],