Search code examples
elasticsearchfilterphrase

Elasticsearch Phrase Match In Filter


I have a query that searches given terms in a text field by given time interval. I want to add phrase match to this query how can I add; for example I'll look for "has parti" as a phrase but the text shouldn't have "ahmet" word. How can I do this; the code is here;

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "terms": {
                "text": [
                  "has",
                  "parti"
                ]
              }
            },
            {
              "range": {
                "date": {
                  "gt": "2015-08-27",
                  "lte": "2015-08-28"
                }
              }
            }
          ]
        }
      }
    }
  }
}

Solution

  • Elasticsearch provides Phrase matching, but I don't think you can use it in the filter, or at least I didn't manage to have it working. I have a solution, with match_phrase in the query, together with the condition that text does not contain ahmet, while the time interval stays in the filter. Check if it's good enough for you.

    {
        "query": {
            "filtered": {
                "query": {
                    "bool": {
                        "must": [
                            {
                                "match_phrase": {
                                    "text": "has parti"
                                }
                            }
                        ],
                        "must_not": [
                            {
                                "match": {
                                    "text": "ahmet"
                                }
                            }
                        ]
                    }
                },
                "filter": {
                    "bool": {
                        "must": [
                            {
                                "range": {
                                    "date": {
                                        "gt": "2015-08-27",
                                        "lte": "2015-08-28"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    }
    

    By the Way, your date looks like being mapped as string, because otherwise your request would fail with

    ElasticsearchParseException[failed to parse date field [2015-08-22], tried both date format [date_time], and timestamp number]; nested: IllegalArgumentException[Invalid format: \"2015-08-22\" is too short]; }]

    I suggest using a proper mapping, but that's not really related to your question

    UPDATE:

    Just came back to add that we did the right thing: filters are not for full-text search

    UPDATE:

    Since the filtered query has been deprecated, in new versions the query should be rewritten in order to move the filter inside the bool query:

    {
    
        "query": {
            "bool": {
                "must": [{
                    "match_phrase": {
                        "text": "has parti"
                    }
                }],
                "must_not": [{
                    "match": {
                        "text": "ahmet"
                    }
                }],
                "filter": {
                    "bool": {
                        "must": [{
                            "range": {
                                "date": {
                                    "gt": "2015-08-27",
                                    "lte": "2015-08-28"
                                }
                            }
                        }]
                    }
                }
            }
        }
    
    }