My index mappings and sample data as follows
I need full text search on these type of documents with following criteria:
country is one input of this search
If I search "Alex 4455" and country is "xxx" this document will be matched and return following document.
If I search "Landing" and country is "xxx" this document will be matched and return following document.
If I search "Martin 4455" and country is "xxx", result is null.
In the other hand, I need combined_field in nested document with filter capability!!!
I try combined_field and saw that is not good for nested document. Also I try query_string and found that not good for my needs!
How can I achieve that a match query for certain fields is equivalent to a term query?
I have a larger index in Elastic covering events. Each event has an eventid field consisting of a random hex string (e.g. f4fc38c993c1a8273f9c40eedc9050b7) as well as some other fields. The eventid is indexed as keyword in Elastic.
If I query based on this field in Kibana, the query often runs into timeouts, because Kibana automatically generates a match query for eventid:f4fc38c993c1a8273f9c40eedc9050b7.
If I set a manual filter using { "query": { "term": { "eventid": "f4fc38c993c1a8273f9c40eedc9050b7" } } } (so a term instead of match query) I get a response quite quickly.
From my understanding, these should be pretty much equivalent, as keyword fields aren't analyzed, so the match query should be equivalent to a term query.
What am I missing?
I'm using ElasticSearch with Ruby (Searchkick). At the moment, by default the where filter is a case sensitive.
I'm using ElasticSearch with my EquityContract model, so once I search for Food I get different results to search for food.
[21] pry(main)> EquityContract.search('*', {:load=>false, :where=>{:industry=>"FOOD"}, limit:1})
effective_url=http://127.0.0.1:9200/equity_contracts_development/_search response_code=200 return_code=ok total_time=0.002279
EquityContract Search (5.9ms) curl http://127.0.0.1:9200/equity_contracts_development/_search?pretty -d '{"query":{"filtered":{"query":{"match_all":{}},"filter":{"and":[{"term":{"industry":"FOOD"}}]}}},"size":1,"from":0}'
=> #<Searchkick::Results:0x0000010b65c5c8
#klass=
EquityContract(id: integer, ticker: text, name: string, country: string, currency: string, instrument: string),
#options=
{:page=>1,
:per_page=>1,
:padding=>0,
:load=>false,
:includes=>nil,
:json=>false,
:match_suffix=>"analyzed",
:highlighted_fields=>[]},
#response=
{"took"=>1,
"timed_out"=>false,
"_shards"=>{"total"=>5, "successful"=>5, "failed"=>0},
"hits"=>{"total"=>0, "max_score"=>nil, "hits"=>[]}}>
While I get some results when I do the same with Food:
[23] pry(main)> EquityContract.search('*', {:load=>false, :where=>{:industry=>"Food"}, limit:1})
ETHON: performed EASY effective_url=http://127.0.0.1:9200/equity_contracts_development/_search response_code=200 return_code=ok total_time=0.002795
EquityContract Search (7.5ms) curl http://127.0.0.1:9200/equity_contracts_development/_search?pretty -d '{"query":{"filtered":{"query":{"match_all":{}},"filter":{"and":[{"term":{"industry":"Food"}}]}}},"size":1,"from":0}'
=> #<Searchkick::Results:0x000001112d1880
#klass=
EquityContract(id: integer, ticker: text, name: string, country: string, currency: string, instrument: string),
#options=
{:page=>1,
:per_page=>1,
:padding=>0,
:load=>false,
:includes=>nil,
:json=>false,
:match_suffix=>"analyzed",
:highlighted_fields=>[]},
#response=
{"took"=>1,
"timed_out"=>false,
"_shards"=>{"total"=>5, "successful"=>5, "failed"=>0},
"hits"=>
{"total"=>73,
"max_score"=>1.0,
"hits"=>
[{"_index"=>"equity_contracts_development_20160320195353552",
"_type"=>"equity_contract",
"_id"=>"1181",
"_score"=>1.0,
"_source"=>
{"name"=>"Some name",
"ticker"=>"some ticker",
"country"=>"SA",
How can I change this to make it more case-insensitive so I'll het the same results for both?
I saw Searchkiq generates term query, but what you need is a full-text query. I'm not familiar with Searchkiq so I can't tell you how.
According to the documentation on ElasticSearch official website,
Term query
Queries like the term or fuzz queries are low-level queries that have no analysis phase. They operate on a single term. A term query for the term Foo looks for that exact term in the inverted index and calculates the TF/IDF relevance _score for each document that contains the term.
Full-text query
Queries like the match or query_string queries are high-level queries that understand the mapping of a field ... If you query a full-text (analyzed) field, they will first pass the query string through the appropriate analyzer to produce the list of terms to be queried.
Elasticsearch has documents indexed with the following fields:
{"id":"1", "title":"test", "locale_1_title":"locale_test"}
Given a query, following behaviour is needed at each document level:
1) If locale_1_title field is not empty(""), search only on locale_1_title field. Do not search on title field.
2) If locale_1_title field is empty, search on title field.
What can be a simple elasticsearch query to get the above behaviour ?
I have a field "animal" that is not_analyzed. Is a document with "animal": "fox"
searchable with a querystring query if a user passes in "fo" as the querystring? Or would the user have to pass in "fox" in order to match that document?
"fo" won't match "fox" if you're using not_analyzed.
There are three types of index mappings in elasticsearch:
analyzed analyses your text and then indexes it. ("fo" matches "fox")
not_analyzed indexes your text (makes it searchable) exactly as it is. ("fo" doesn't match "fox", only "fox" does)
no the field is not searchable.
reference
If you search for fo* it will work , else you need to search for the exact term.