25

I am trying to query an Elasticsearch index by a time range, and additionally have a term match a specific string value.

I have tried this query, which seems pretty straightforward:

 {
  "query" : {
    "bool": {
      "must": [
        {
          "match": {
            "method": "/customer/help"
          }
        },
        {
          "range" : {
            "startTime": {
              "from" : "2015-10-20T13:00-04:00",
              "to" : "2015-10-20T14:00-04:00"
            }
          }
        }
      ]
    }
  }
}

In this case, I want all of the documents within the given time range that also have a method value of "/customer/help".

In my results, I am receiving results that are within the time range, but I am getting documents that have various values for the "method" field, when I just want results with "/customer/help" in that field.

Andrei Stefan
  • 51,654
  • 6
  • 98
  • 89
smithzo622
  • 453
  • 1
  • 7
  • 15
  • 1
    Are the various values for "method" field values that have either "customer" or "help" along with results that have the expected "customer/help"? In that case the problem is that Elasticsearch is analyzing the field (probably Standard analyzer if you have not specified the mapping). If you don't expect to use the analyzer for that field in the future, then you can set "index" : "not_analyzed" property for that field. – eemp Oct 20 '15 at 20:45
  • The other values do have customer/ but what is weird is that if I run a query separately where I am excluding the range, I only get results where the method = "customer/help". – smithzo622 Oct 20 '15 at 21:09
  • What are you passing for the size param? Is it just a coincidence and you are only seeing a subset of all results when you cut out the range query? – eemp Oct 20 '15 at 22:29
  • You should use a `term` query instead of `match` query if you're looking for exact matches for your `method` field. – Val Oct 21 '15 at 03:15
  • Somebody visiting this post should also look at this, https://stackoverflow.com/questions/49556729/how-to-have-range-and-match-query-in-one-elastic-search-query-using-python – Deepan Prabhu Babu Oct 17 '19 at 19:55

1 Answers1

42

In your mapping you need to have method as not_analyzed (or analyzed with keyword analyzer) and the query should use term. In this way, the text you index in method is indexed as is as a single token and term makes sure the text you search matches exactly the token indexed in method:

    "method": {
      "type": "string",
      "index": "not_analyzed"
    }

And the query you need to use:

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "method": "/customer/help"
          }
        },
        {
          "range": {
            "startTime": {
              "from": "2015-10-20T13:00-04:00",
              "to": "2015-10-20T14:00-04:00"
            }
          }
        }
      ]
    }
  }
}
Andrei Stefan
  • 51,654
  • 6
  • 98
  • 89
  • 2
    Yeah it turns out it was tokenizing that string therefore skewing the results. This answer is correct, and thanks! Also I thought it would be helpful to point out that using the "match_phrase" query instead of the "match" query achieved the correct results as well without changing the index. – smithzo622 Oct 21 '15 at 13:36