# Proximity between multiple (boolean) queries

**URL:** <https://discuss.elastic.co/t/proximity-between-multiple-boolean-queries/63382>\
**Category:** Elasticsearch\
**Created:** [October 19, 2016, 11:12am UTC](https://discuss.elastic.co/t/proximity-between-multiple-boolean-queries/63382 "2016-10-19T11:12:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kno3](https://avatars.discourse-cdn.com/v4/letter/k/ea5d25/32.png) [@kno3](https://discuss.elastic.co/u/kno3)\
**Post date:** [October 19, 2016, 11:12am UTC](https://discuss.elastic.co/t/proximity-between-multiple-boolean-queries/63382/1 "2016-10-19T11:12:32Z")

</div>

I have a boolean which retrieves documents with 2 specific keywords/phrases (keyword one and keyword two):

```
        "query": {
        "bool":{
            "must": [
                {"match_phrase": {"main_text": "keyword one"}},
                {"match_phrase": {"main_text": "keyword two"}}
            ]
        }
        }

```

Is it possible to add proximity between "keyword one" and "keyword two"? I.e. given these documents:

_Document 1_: this document contains both _ **keyword one** _ and **_keyword two_**.  
_Document 2_: this document contains _ **keyword one** _ as well as other keywords, including **_keyword two_**.  
_Document 3_: this documents contains keywords. **_Keyword one_** refers to a topic that is very interesting. One should definitely look into it. **_Keyword two_** is boring.

I need to retrieve all of these 3 documents because they contain both phrases, but need to add weights to phrases/keywords that are closer to each other; in this case document 1 \> document 2 \> document 3. Sort of "slop" between the different queries rather than within each one (because keyword one should be matched exactly, and same for keyword two).

Cheers

---

<div class="post-metadata">

**Author:** ![cbuescher](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/cbuescher/32/60402_2.png) [@cbuescher](https://discuss.elastic.co/u/cbuescher)\
**Post date:** [October 19, 2016, 2:03pm UTC](https://discuss.elastic.co/t/proximity-between-multiple-boolean-queries/63382/2 "2016-10-19T14:03:24Z")

</div>

Hi,

I was going to suggest to take a look at [Span Queries](https://www.elastic.co/guide/en/elasticsearch/reference/current/span-queries.html), but since they are a bit messy to use I thought about another thing and it seems to work at least for the simple test case you mentioned:

```auto
PUT /test/t/1
{
  "main_text" : "this document contains both keyword one and keyword two"
}

PUT /test/t/2
{
  "main_text" : "this document contains keyword one as well as other keywords, including keyword two"
}

PUT /test/t/3
{
  "main_text" : "this documents contains keywords. Keyword one refers to a topic that is very interesting. One should definitely look into it. Keyword two is boring."
}

PUT /test/t/4
{
  "main_text" : "this keyword is one and another keyword is two, but I don't want to see them both"
}

GET /test/t/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "match_phrase": {
            "main_text": "keyword one"
          }
        },
        {
          "match_phrase": {
            "main_text": "keyword two"
          }
        }
      ],
      "should": [
        {
          "match_phrase": {
            "main_text": {
             "query" : "keyword one keyword two",
            "slop" : 100
            }
          }
        }
      ]
    }
  }
}

```

The `filter` part ensures that you only get back documents with both keywords, but they have a constant score. The `should` clause is supposed to increase the score for documents where the contained terms are closer together within a certain `slop` distance. I don't know how much of a slop is acceptable here for your case.

This is somewhat of a quick hack but it might get you somewhere. Keep in mind that real world examples might be much messier than the three toy documents mentioned here (what happens e.g. if there are multiple occurences of keywords throughout the text? Which distance do you want to be applied there etc...). Also, phrase matching with slop comes with a certain performance cost. If you really want this to run as fast as possible you should think about [shingling](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-shingle-tokenfilter.html) your test (so you can match e.g. Bigramms directly). Also using the "distance scoring" part of the query only in the [rescoring phase](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-rescore.html) might help in terms of performance cost.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 5, 2017, 10:11pm UTC](https://discuss.elastic.co/t/proximity-between-multiple-boolean-queries/63382/3 "2017-07-05T22:11:13Z")

</div>


