如何在ElasticSearch中筛选多值数组字段包含非指定值的文档
Got it, let's break down why your current query isn't working and fix it.
The Problem with Your Current Query
Your existing query:
{ "query": { "bool": { "must_not": [ { "term": { "fruit": "banana" } } ] } } }
is excluding any document that has "banana" in the fruits array at all—even if there are other fruits present (like Ahmed's record with both apple and banana). That's why you're missing document 1. What you actually want is to exclude only documents where every element in the fruits array is banana (i.e., Bryce's record), while keeping docs that have banana plus other fruits, or no banana at all.
Correct Query Solutions
Here are two solid approaches to get your desired results:
Approach 1: Exclude Documents with Only Banana
This is the most flexible option because it doesn't require you to know all possible non-banana fruits upfront. We'll check if the document's fruits array contains banana and has exactly one element (meaning it's only banana):
{ "query": { "bool": { "must_not": [ { "bool": { "must": [ { "term": { "fruits": "banana" } }, { "script": { "source": "doc['fruits'].size() == 1" } } ] } } ] } } }
If you prefer a script-free alternative (and your fruits field is mapped as keyword, which it should be for term queries), use the terms_set query to match when the number of banana entries equals the total array size:
{ "query": { "bool": { "must_not": [ { "terms_set": { "fruits": { "terms": ["banana"], "minimum_should_match_script": { "source": "doc['fruits'].size()" } } } } ] } } }
Approach 2: Directly Match Documents with Non-Banana Fruits
If you know all the non-banana fruit values you care about, you can explicitly match those while allowing banana to be present too:
{ "query": { "bool": { "must": [ { "exists": { "field": "fruits" } }, { "bool": { "should": [ { "term": { "fruits": "apple" } }, { "term": { "fruits": "mango" } }, // Add any other non-banana fruits here, or use a wildcard for flexibility { "wildcard": { "fruits": "*" }, "boost": 0 } ], "minimum_should_match": 1 } } ] } } }
This ensures the document has at least one non-banana fruit, regardless of whether banana is present.
Why This Works
Unlike your original query, these solutions don't blanket-ban any document with banana. Instead, they either:
- Only exclude docs where banana is the only fruit, or
- Explicitly include docs that have at least one non-banana fruit.
Either way, you'll get the desired results: Ahmed's and Caitlin's records.
内容的提问来源于stack exchange,提问作者Archit Jain

