Exact match in elastic search query
As stated here: Finding Exact Values, since the field has been analyzed when indexed - you have no way of exact-matching its tokens (":"). Whenever the tokens should be searchable the mapping should be "not_analyzed" and the data needs to be re-indexed.
If you want to be able to easily match only ":feed:" inside the message field you might want to costumize an analyzer which doesn't tokenize ":" so you will be able to query the field with a simple "match" query instead of wild characters.
How to get elasticsearch to perform an exact match query?
If you have your source stored (which is the default) you can use a script filter
It should go something like this:
$ curl -XPUT localhost:9200/index/type/1 -d '{"foo": "bar"}'
$ curl -XPUT localhost:9200/index/type/2 -d '{"foo": "bar baz"}'
$ curl -XPOST localhost:9200/index/type/_search?pretty=true -d '{
"filter": {
"script": {
"script": "_source.foo == \"bar\""
}
}
}'
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [ {
"_index" : "index",
"_type" : "type",
"_id" : "1",
"_score" : 1.0, "_source" : {"foo": "bar"}
} ]
}
}
EDIT: I think it's worth mentioning that the "not_analyzed" mapping should be the faster approach. But if you want both exact and partial matches for this field, I see two options: use scripts or index the data twice (once analyzed, once not analyzed).
How to implement an exact match in a filter with elasticsearch?
Update : As OP mentioned in the comment that he is using 2.4, I am updating my solution to include the solution which works for it.
ES 2.4 solution
Index creation with required settings and mappings
{
"settings": {
"analysis": {
"analyzer": {
"lckeyword": {
"filter": [
"lowercase"
],
"tokenizer": "keyword"
}
}
}
},
"mappings": {
"so": {
"properties": {
"state": {
"type": "string"
},
"city": {
"type": "string"
},
"colony": {
"type": "string"
},
"state_raw": {
"type": "string",
"analyzer": "lckeyword"
}
}
}
}
}
Search query
{
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{
"match": {
"state": {
"query": "michoacán de ocampo"
}
}
},
{
"match": {
"colony": {
"query": "zamora"
}
}
},
{
"match": {
"city": {
"query": "zamora"
}
}
}
]
}
},
"filter": {
"term": {
"state_raw": "michoacán de ocampo"
}
}
}
}
}
An important thing to note here is creating a custom analyzer(keyword with lowercase filter), so that field on which we are creating filter stored as it is but with small letter, as that is what you are passing in your query. Now above query returns you both your document, this is the postman collection that has index creation, sample docs creation and query which return both docs returned.
ES 7.X solution
The issue is that you are defining your state
field as text
field and then in your filter, you are using [term][1]
query which is not analyzed as explained in official ES doc.
Returns documents that contain an exact term in a provided field.
Hence it would try to find token `Michoacán de Ocampo` in inverted index which isn't present as state field is defined as text and generates 3 tokens `michoacán`, `de` and `ocampo` and ES works on token(search term) to token(inverted index) match. You can check these tokens with [analyze API][2] and can use [explain API][3] to see the tokens generated by ES when the query has results
Fix
---
Define `state` field as a [multi-field][4] and store it as it is(kwyword form) so that you can filter on it.
{
"mappings": {
"properties": {
"state": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
},
"city": {
"type": "text"
},
"colony": {
"type": "text"
}
}
}
}
Now below query would give you both results.
{
"query": {
"bool": {
"must": [
{
"match": {
"state": {
"query": "michoacán de ocampo"
}
}
},
{
"match": {
"colony": {
"query": "zamora"
}
}
},
{
"match": {
"city": {
"query": "zamora"
}
}
}
],
"filter": {
"term": {
"state.raw": "Michoacán de Ocampo" -->notice .raw to search on keyword field.
}
}
}
}
}
EDIT: - https://www.getpostman.com/collections/f4b9ed00d50e2f4bc7f4 is the postman collection link if you want to quickly test it.
Elasticsearch query not giving exact match
Instead of match
you have to use term
query, as the documentation describe:
The term query finds documents that contain the exact term specified in the inverted index
So you have to change your query as follow:
get items/_search
{
"query" : {
"term" : {
"code.keyword" : "7000-8900"
}
}
}
If you don't get any result there are two possibilities:
- The term searched is not what you think it really is (for example is not trimmed)
- The index has no explicit mapping and the automatic mapping didn't recognize the field code as a string.
Note: if the mapping is correct and code is a term field it is possible to use "code". If the mapping was automatic and the mapping recognize it as text you need to use "code.keyword"
How to search query by field with exact match in Elasticsearch
You need to use term
query with keyword like this
{
"query" : {
"term" : {
"field.keyword" : "test"
}
}
}
hope this helps.
Elasticsearch - How to list exact match at the top
If you want your exact matches to be on top, you could use a keyword
field in your mapping.
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 3,
"max_gram": 15
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
},
"analyzer": "autocomplete",
"search_analyzer": "standard"
}
}
}
}
}
Then you can have a bool
query that uses your keyword
in the should
query.
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "Adana"
}
}
],
"should": [
{
"term": {
"name.keyword": {
"value": "Adana"
}
}
}
]
}
}
}
That should push the exact match to the top.
Elasticsearch query to find exact match on string field ( Without analyzing )
The mapping influences how your data gets stored and how you can query that field. Your category field (named name)field is configured to be used for auto-complete and not for exact-match search. So you have to change the mapping in order to support exact match-search.
However, you can do so without changing the current field, but simply by adding an additional field by converting your field to a multi-field and adding a field that supports exact-match queries. Mapping snippet:
"name": {
"type": "string",
"analyzer": "autocomplete",
"search_analyzer": "standard",
"fields": {
"raw": {
"type" "string",
"index": "not_analyzed"
}
}
}
}
Note: I noticed that you are on an older version of Elasticsearch (the type "string" got replaced with types "text" (for full-text-search) and "keyword" (for exact match search). I tried to come up with a mapping that works with older versions of Elasticsearch and hope it works. If not you need to provide the version of Elasticsearch you are using.
After fixing the mapping, you need to ensure that the field is also populated. You can do so, by getting everything re-indexed, by executing the following request:
POST <your_index_name>/_update_by_query
In your query you would then need to search as follows (for exact-match):
"match": {
"category.name.raw": "Arts and Culture"
}
For partial searches you would continue using the category.name
-field (without suffix raw)
how to do exact match in elastic search?
The problem is because your sysid
field is of type text
and is thus analyzed at indexing time and tokenized into fcf0dd4e
, abbc
, ec11
, 8943
and 000d3a15f525
.
Also when searching using a match query, the searched term is analyzed as well into the following tokens 6a8c283f
, 1e75
, ec11
, 8943
, 000d3a15f525
.
As you saw, the match works because ec11
matches.
For an exact match, what you need to do is to run your query against a keyword
field instead. Maybe you're lucky and your mapping already contains a sysid.keyword
sub-field. If not, you need to change your mapping and reindex your data.
Then you'll be able to run your term
query like this and get your exact match:
"term": {
"sysid.keyword":sysid
}
Related Topics
Python - Returning Nan When Trying to Predict With Keras
How to Use a Module Without Installing It on Your Computer
Valueerror: Too Many Values to Unpack (Expected 2) in Django
How to Get a Value from a Cell of a Dataframe
How to Check Whether All Elements of Array Are in Between Two Values
Converting Text File into Json in a Specific Format ( Python )
Importerror: No Module Named Sklearn (Python)
Split Datetime Column into a Date and Time Python
Pandas Extract Numbers from Column into New Columns
Python Replace Empty Strings in a List With Values from a Different List
Ioerror: [Errno 32] Broken Pipe When Piping: 'Prog.Py | Othercmd'
Getting the Bounding Box of the Recognized Words Using Python-Tesseract
How to Pass a .Txt File to a Function in Python
Flask Installed, But Modulenotfounderror: No Module Named 'Flask'
How to Delete a Record by Id in Flask-Sqlalchemy
Jupyter Notebook, Python3 Print Function: No Output, No Error
I Am Trying to Split a Full Name to First Middle and Last Name in Pandas But I Am Stuck At Replace