Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

query_string and range at the same time

How is it possible to have both query_string and range in the same query?

I am sending this to /myindex/mytype/_search/?search_type=count:

 {"query": {"query_string": {"query": "field1:value1"},
            "range": {"time": {"gt": "2014-11-01T00:00:00Z",
                               "lte": "2014-11-01T03:00:00Z"}}},
  "aggs": {"counts": {"date_histogram": {"field": "time",
                                         "interval": "minute"}}}}

But ES gives me this error:

ElasticsearchParseException[Expected field name but got START_OBJECT \"range\"];

If I remove either range or query_string, it works just fine, but without the much needed filtering :)

like image 825
Mischa Arefiev Avatar asked Dec 09 '22 04:12

Mischa Arefiev


2 Answers

From what you are saying, it seems you want to combine multiple queries to reduce the scope on which you are computing aggregations.

First, this can be achieved using a bool query (documentation) that lets you decide if a document must match both queries (see the must clause) or at least one of the queries (see should clause).

Let's say you want your result documents to match both queries, the syntax will be :

{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            ...
          }
        },
        {
          "range": {
            ...
          }
        }
      ]
    }
  }
}

This will work, but this not the optimal way to query. It could be optimized as your range query has an equivalent filter.

Using the filter version will be generally faster, as it will skip the score computation, and will hit the cache for most of the filter types (more information about the differences between queries and filters here).

However, a filter can't be used directly in the query attribute, you have to wrap it in a filtered query which has two attributes :

  • query : the query to be filtered
  • filter : the filter to combine with your query

Finally, you'll have a query like this one :

{
  "query": {
    "filtered": {
      "query": {
        "query_string": {
          "query": "field1:value1"
        }
      },
      "filter": {
        "range": {
          "time": {
            "gt": "2014-11-01T00:00:00Z",
            "lte": "2014-11-01T03:00:00Z"
          }
        }
      }
    }
  },
  "aggs": {
    "counts": {
      "date_histogram": {
        "field": "time",
        "interval": "minute"
      }
    }
  }
}
like image 186
ThomasC Avatar answered Jan 05 '23 12:01

ThomasC


I believe, you want something like:

{
    "query": {
        "bool": {
            "must": [
                {
                    "range": {
                        "time": {
                            "gt": "2014-11-01T00:00:00Z",
                            "lte": "2014-11-01T03:00:00Z"
                        }
                    }
                },
                {
                    "query_string": {
                        "query": "field1:value1"
                    }
                }
            ]
        }
    }
}

Elasticsearch doesn't seem to let you chain multiple things together under a single "query" tag.

(Sorry about formatting, I can't make { look pretty and lined up.)

like image 39
TZHX Avatar answered Jan 05 '23 11:01

TZHX