2

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"
                }
              }
            }
          ]
        }
      }
    }
  }
}
Fatih Aktepe
  • 571
  • 2
  • 10
  • 19

2 Answers2

4

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"
                            }
                        }
                    }]
                }
            }
        }
    }

}
Mario Trucco
  • 1,933
  • 3
  • 33
  • 45
1

You will need to use phrase match query. But then as this is a query and as you are looking for a filter , you need to wrap this in query filter.

Once this is done , you should be able to implement phrase match filter. Next as you need a negation , put your statement inside must_not of the bool filter. You can use term filter for the same.

So finally your query should look something like this -

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must_not": [
            {
              "term": {
                "title": "ahmet"
              }
            }
          ],
          "must": [
            {
              "range": {
                "date": {
                  "gt": "2015-08-27",
                  "lte": "2015-08-28"
                }
              }
            },
            {
              "constantScore": {
                "filter": {
                  "query": {
                    "match_phrase": {
                      "title": "has parti"
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }
  }
}
Vineeth Mohan
  • 18,633
  • 8
  • 63
  • 77