Search code examples
pythonelasticsearchelasticsearch-dslelasticsearch-query

Elasticsearch - How to add range filter to search query


I use elasticsearch-dsl in order to query Elasticsearch in python.
I want to search documents with text field and get all documents that created field of them is less than datetime.now().
I execute the following query but elasticsearch raises error.

q = "some word"
es.search(
        index="comment",
        body={
            "query": {
                "query_string": {
                    "query": f"*{q}*" ,
                    "default_field": "text"
                },
                "range": {"created": {"lt": datetime.now()}}
            },
            "fields": ["id"],
            "size": 10
        },
    )

The following is elasticsearch error:

elasticsearch.exceptions.RequestError: RequestError(400, 'parsing_exception', '[query_string] malformed query, expected [END_OBJECT] but found [FIELD_NAME]')

Note: When I comment "range": {"created": {"lt": datetime.now()}}, the query will work without error (but datetime filter is not applied).


Solution

  • You can't combine few types of queries like this, use bool:

    {
      "query": {
        "bool": {
          "must": [{"query_string": {"query": f"*{q}*" , "default_field": "text"}}],
          "filter": [{"range": {"created": {"lt": datetime.now()}}}]}
        }
      }
    }
    

    Notice that full-text query_string clause goes into must section and gets scored while range filter goes to filter and ES doesn't calculate scores for these.