title: Combine elasticsearch bool query with range boost
body: <p>Combine elasticsearch bool query with range boost</p>
  
  <p>I have a complex <code>bool</code> query as follows. I use a bogus search term <code>dgbdrtgndgfndrtgb</code> to fabricate my example, which should not match anything.</p>
  
  <pre><code>{
    "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
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
  }
  </code></pre>
  
  <p>This works well. Now, for any of those matches, I want to add a <code>boost</code> where the <code>name</code> field has fewer than 2 words. In other words, boost single-word matches or sort them to the top of the result set.</p>
  
  <p>So I tried adding a <code>range</code> boost like this:</p>
  
  <pre><code>{
    "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
                      }
                    }
                  }               
                ]
              }
            }
          }
        }
      }
    }
  }
  </code></pre>
  
  <p>This sorts things like I want, but it also returns single-word matches which do not match the search term <code>dgbdrtgndgfndrtgb</code>. </p>
  
  <p>Is there a way to only boost single-word matches, which also match the search term? I've tried lowering the <code>boost</code> value, which breaks the desired sorting when using a valid (found) search term.</p>
  
  <p>It seems like there should be a way to <code>AND</code> the entire <code>bool</code> query with the <code>range</code> boost. I've tried various permutations to achieve this with no luck and the docs are less than helpful.</p>
  
  <p>One caveat: I cannot use scripting as the index is hosted on AWS which doesn't support it.</p>
  
  <p>Any advice is appreciated.</p>