Combine elasticsearch bool query with range boost
I have a complex bool
query as follows. I use a bogus search term dgbdrtgndgfndrtgb
to fabricate my example, which should not match anything.
{
"from": 0,
"size": 10,
"query": {
"function_score": {
"boost_mode": "replace",
"query": {
"filtered": {
"filter": {
# ...
},
"query": {
"bool": {
"should": [
{
"match": {
"name.suggest_ngrams": {
"query": "dgbdrtgndgfndrtgb",
"fuzziness": "AUTO",
"prefix_length": 1,
"operator": "AND",
"boost": 10
}
}
},
{
"multi_match": {
"query": "dgbdrtgndgfndrtgb",
"fields": [
"name.untouched_lowercase"
],
"boost": 5
}
},
{
"query_string": {
"fields": [
"name.suggest"
],
"query": "dgbdrtgndgfndrtgb*",
"boost": 10
}
},
{
"query_string": {
"fields": [
"name.suggest"
],
"query": "dgbdrtgndgfndrtgb",
"boost": 10
}
},
{
"match": {
"first_word": {
"query": "dgbdrtgndgfndrtgb",
"operator": "AND",
"boost": 10
}
}
},
{
"match": {
"name": {
"query": "dgbdrtgndgfndrtgb",
"operator": "AND",
"boost": 5
}
}
}
]
}
}
}
}
}
}
}
This works well. Now, for any of those matches, I want to add a boost
where the name
field has fewer than 2 words. In other words, boost single-word matches or sort them to the top of the result set.
So I tried adding a range
boost like this:
{
"from": 0,
"size": 10,
"query": {
"function_score": {
"boost_mode": "replace",
"query": {
"filtered": {
"filter": {
# ...
},
"query": {
"bool": {
"should": [
{
"match": {
"name.suggest_ngrams": {
"query": "dgbdrtgndgfndrtgb",
"fuzziness": "AUTO",
"prefix_length": 1,
"operator": "AND",
"boost": 10
}
}
},
{
"multi_match": {
"query": "dgbdrtgndgfndrtgb",
"fields": [
"name.untouched_lowercase"
],
"boost": 5
}
},
{
"query_string": {
"fields": [
"name.suggest"
],
"query": "dgbdrtgndgfndrtgb*",
"boost": 10
}
},
{
"query_string": {
"fields": [
"name.suggest"
],
"query": "dgbdrtgndgfndrtgb",
"boost": 10
}
},
{
"match": {
"first_word": {
"query": "dgbdrtgndgfndrtgb",
"operator": "AND",
"boost": 10
}
}
},
{
"match": {
"name": {
"query": "dgbdrtgndgfndrtgb",
"operator": "AND",
"boost": 5
}
}
},
{
"range": {
"name.word_count": {
"lt": 2,
"boost": 40
}
}
}
]
}
}
}
}
}
}
}
This sorts things like I want, but it also returns single-word matches which do not match the search term dgbdrtgndgfndrtgb
.
Is there a way to only boost single-word matches, which also match the search term? I've tried lowering the boost
value, which breaks the desired sorting when using a valid (found) search term.
It seems like there should be a way to AND
the entire bool
query with the range
boost. I've tried various permutations to achieve this with no luck and the docs are less than helpful.
One caveat: I cannot use scripting as the index is hosted on AWS which doesn't support it.
Any advice is appreciated.