voidMainReturn
voidMainReturn

Reputation: 3537

elasticsearch query_string keyword search with or operator not working

I have created a simple reproducer for this issue as following :

PUT trial
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "type": "custom",
          "tokenizer": "whitespace",
          "filter": [ "lowercase" ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "status": {
        "type": "keyword"
      }
    }
  }
}
PUT trial/_doc/2
{
  "status": "not_installed"
}

PUT trial/_doc/1
{
  "status": "installed"
}
POST trial/_search
{
  "from": 0,
  "size": 20,
  "query": {
    "bool": {
      "filter": [
        {
          "query_string": {
            "query": "not_installed installed",
            "default_operator": "or"
          }
        }
      ]
    }
  }
}

If I execute these commands from top to bottom one by one, I expect doc 1,2 as results. But it's not getting fetched. What is wrong with my understanding ? Can someone help ? Working with ES version 7.4

Upvotes: 2

Views: 1752

Answers (1)

Bhavya
Bhavya

Reputation: 16192

Try this below search query (taking same index mapping and data)

{
  "from": 0,
  "size": 20,
  "query": {
    "bool": {
      "filter": [
        {
          "query_string": {
            "query": "not_installed OR installed"
          }
        }
      ]
    }
  }
}

The above query gives the expected result. To know more about query_string refer to this documentation.

UPDATE 1:

Elasticsearch relies on the analyzer to split everything that is in-between query operators into terms. And the analyzer on keyword fields is a keyword analyzer.

So there has to be a way to configure keyword fields so that text would be split on whitespace at query time. Therefore, split_queries_on_whitespace parameter is added to the field that sets a whitespace analyzer as a search analyzer when set to true. By adding this parameter and setting it to true full-text queries (match, multi_match, query_string,..) that target the field will split the input on whitespace to build the query terms.

Refer to these GitHub issues to know more about this:

https://github.com/elastic/elasticsearch/issues/29148 https://github.com/elastic/elasticsearch/issues/30131 https://github.com/elastic/elasticsearch/issues/30393 https://github.com/elastic/elasticsearch/pull/30691

In your case you need to add split_queries_on_whitespace parameter to the keyword field to split the input on whitespace when building a query for the field status. To know more about this refer to this official documentation on Keyword datatype.

Index Mapping:

Modified mapping will look like this :

{
  "settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "type": "custom",
          "tokenizer": "whitespace",
          "filter": [ "lowercase" ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "status": {
        "type": "keyword",
        "split_queries_on_whitespace": true   --> note this
      }
    }
  }
}

Search Query :

{
  "from": 0,
  "size": 20,
  "query": {
    "bool": {
      "filter": [
        {
          "query_string": {
            "query": "installed not_installed",
            "default_operator":"OR"
          }
        }
      ]
    }
  }
}

Search Result:

"hits": [
      {
        "_index": "my_index",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.0,
        "_source": {
          "status": "not_installed"
        }
      },
      {
        "_index": "my_index",
        "_type": "_doc",
        "_id": "2",
        "_score": 0.0,
        "_source": {
          "status": "installed"
        }
      }
    ]

Upvotes: 1

Related Questions