Luke
Luke

Reputation: 760

Elasticsearch query with wildcards

Use their data on Elasticsearch tutorials as an example, the following uri search hits 9 records,

curl -XGET 'remotehost:9200/bank/_search?q=city:R*d&_source_include=city&pretty&pretty'

while the following reques body search hits 0 records,

curl -XGET 'remotehost:9200/bank/_search?pretty' -H 'Content-Type: application/json' 
 -d'{"query": {"wildcard": {"city": "R*d"} },
 "_source": ["city"]
}
'

But the two methods shoud be equivalent to each other. Any idea why this is happening? I use Elasticsearch 5.5.1 in docker.

Upvotes: 2

Views: 1577

Answers (1)

sunkuet02
sunkuet02

Reputation: 2442

You can get your expected result by hitting the below command. This commands add an extra .keyword with your command in field city.

curl -XGET 'localhost:9200/bank/_search?pretty' -H 'Content-Type: application/json' -d'{"query": {"wildcard": {"city.keyword": "R*d"} }, "_source": ["city"]}'

Reason of adding .keyword

When you insert data to elasticsearch, you will notice a .keyword field and that field is not_analyzed. By default, the field you have inserted data, is standard analyzed and there is a multifield .keyword . If you create a field city with data, then it create a field city with standard analyzer and added a multifield .keyword which is not_analyzed.

In your case you need a not_analyzed field to query (as wildcard query). So, your query should be on city.keyword field which is by default not_analyzed.

In the first case, you have hit a get request to elasticsearch with query parameter. Elasticsearch will automatically converted the query as like second format.

For reliable source, you can follow the Official docs

The string field has split into two new types: text, which should be used for full-text search, and keyword, which should be used for keyword search.

To make things better, Elasticsearch decided to borrow an idea that initially stemmed from Logstash: strings will now be mapped both as text and keyword by default. For instance, if you index the following simple document:

{
  "foo": "bar"
}

Then the following dynamic mappings will be created:

{
  "foo": {
    "type" "text",
    "fields": {
      "keyword": {
        "type": "keyword",
        "ignore_above": 256
      }
    }
  }
}

As a consequence, it will both be possible to perform full-text search on foo, and keyword search and aggregations using the foo.keyword field.

Upvotes: 2

Related Questions