Reputation: 55
I'm trying to write an elasticsearch bool query which checks if a field exists in an object, and then attempts to match a string in that field which may or may not exist. I want the query to return all objects (posts) which satisfy one of the following conditions: 1. the field postMeta.byline does not exist 2. if postMeta.byline does exist, then it contains the string "John Doe"
Here's the latest query I've attempted, which does not work:
{ "query":
{ "bool":
{ "filter":
[ { "match": { "status": "publish" } },
{ "match": { "authors": "104" } }
],
"should": [
{ "must_not": { "exists": { "field": "postMeta.byline" } } },
{ "filter": {
"wildcard": {
"postMeta.byline": "*John Doe*"
}
}
}
]
}
}
}
Upvotes: 1
Views: 2001
Reputation: 1267
In bool query, should will have no effect if you already have must or filter. Following is documented here-
The clause (query) should appear in the matching document. If the bool query is in a query context and has a must or filter clause then a document will match the bool query even if none of the should queries match. In this case these clauses are only used to influence the score.
What you can try is nested bool query.
{ "query":
{ "bool":
{ "filter":
[ { "match": { "status": "publish" } },
{ "match": { "authors": "104" } } ,
{ "bool" :
{ "should" : [
{ "bool": { "must_not": { "exists": { "field": "postMeta.byline" } } } },
{ "wildcard": { "postMeta.byline": "*John Doe*" } }
]
}
}
]
}
}
}
First bool has three clauses in filter. So, it will match all the three. Nested bool has should. So, it will match at least one of two.
I have not tested the query.
Upvotes: 1
Reputation: 55
Thanks @nitzien, for your response! Your query almost worked; the only change I had to make was to wrap the "must_not" clause in another "bool" clause as follows:
{ "query":
{ "bool":
{ "filter":
[ { "match": { "status": "publish" } },
{ "match": { "authors": "104" } } ,
{ "bool" :
{ "should" : [
{ "bool": { "must_not": { "exists": { "field": "postMeta.byline" } } } },
{ "wildcard": { "postMeta.byline": "*John Doe*" } }
]
}
}
]
}
}
}
Upvotes: 1