I have an ES 6.5 index with the following mappings –
<code>{
"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"
}
}
}
}
}
}
</code>
<code>{
"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"
}
}
}
}
}
}
</code>
{
"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 –
<code>{
"name": "Hotel with amenities",
"hotelStatus": "BOOKABLE",
"hotelAmenities": [
{
"key": "POOL",
"name": "Pool",
"enabled": true,
"featured": true
},
{
"key": "LAUNDRY",
"name": "Laundry",
"enabled": true,
"featured": true
}
]
}
</code>
<code>{
"name": "Hotel with amenities",
"hotelStatus": "BOOKABLE",
"hotelAmenities": [
{
"key": "POOL",
"name": "Pool",
"enabled": true,
"featured": true
},
{
"key": "LAUNDRY",
"name": "Laundry",
"enabled": true,
"featured": true
}
]
}
</code>
{
"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.
<code>{
"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
}
</code>
<code>{
"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
}
</code>
{
"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.
<code>{
"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
}
</code>
<code>{
"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
}
</code>
{
"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?