elasticsearch multi_match vs should - elasticsearch

Can someone tell me the difference between
"query": {
"bool": {
"should": [
{ "match": {"title": keyword} },
{ "match": {"description": keyword} }
]
}
and
"query": {
"multi_match": {
"query": keyword,
"fields": [ "title", "description" ]
}
}
Is there any performance turning if choose one of two above?

It depends on the type parameter of your multi_match. In your example, since you didn't specify a type, best_fields is used. That makes use of a Dis Max Query and basically
uses the _score from the best field
On the other hand, your example with should
combines the _score from each field.
and it is equivalent to multi_match with type most_fields

Related

Fuzzy sentence search in elasticsearch based on edit distance of words

For a given index I have added documents like:
[
{"expression": "tell me something about elasticsearch"},
{"expression": "this is a new feature for elasticsearch"},
{"expression": "tell me something about kibana"},
# ... and so on
]
Now, I want to query elastic search in a such a that for given input expression:
"tell me something on elasticsearch". It must give out:
{"expression": "tell me something about elasticsearch"},
{"expression": "tell me something about kibana"}
Since it this case edit distance w.r.t. to words (not character level) is less in this case.
Can we perform such a query on elasticsearch?
as per my understanding fuzziness does not allow type phrase/match phrase.
But let me share few use cases for you and try if these are helpful.
If you want to perform search ignoring missing words use slop with match_phrase and not fuzziness(this may work for you)
GET demo_index/_search
{
"query": {
"match_phrase": {
"field1": {
"query": "tell me something elasticsearch",
"slop": 1 -----> you can increase it as per your requirement
}
}
}
}
Secondly if you want to perform search on character level changes you can use below queries with fuzziness
Single search on different fields
GET index_name/_search
{
"query": {
"bool": {
"should": [
{
"multi_match": {
"query": "enginere", -----> Wrong spelling but still we will get result wherever query match **engineer** keyword. Again you can increase fuzziness.
"fields": [
"field_name1",
"field_name2",
...
],
"fuzziness": 1,
"slop": 1 -----> not compulsory
}
}
]
}
}
}
Multi search in different fields
GET index_name/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"field1": {
"query": "text1",
"fuzziness": 1
}
}
},
{
"match": {
"field2": {
"query": "text2",
"fuzziness": 2
}
}
}
],
"filter": [
{
"match": {
"field3": "text3"
}
}
]
}
}
}

Elasic search: find doc by id and highlight words based on query string

I like to find an document in elastic search an highlight terms based on an query string.
Is this possible?
I tried to run an query-string elastic search and filter the result based on ID. But those sounds not very efficient, because elastic first generates an huge list of all document matched the querystring (which could by millions) an pic only one document based on the filter.
Is there a way or query-contstruct to combine querystring and "search for term in _id field" in one boolean search?
Something like this (which is not working):
"query": {
"bool": {
"must": {
"query_string": {
"query": "red*",
"fields": [
"text",
"title"
]
},
"term": {
"_id":"fda72434fa172"
}
}
}
},
"highlight": {
"fields": {
[...]
I made a small example that can be a starting point.
Use filter to perform your query and retrieve the doc by id.
Then I used match and highlight to highlight the term I want.
POST test/_doc/fda72434fa172
{
"text": "I like to find an document in elastic search an highlight terms based on an query string. Is this possible?"
}
GET test/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"_id": "fda72434fa172"
}
}
],
"must": [
{
"match": {
"text": {
"query": "elastic search"
}
}
}
]
}
},
"highlight": {
"fields": {
"text": {}
}
}
}

Get ElasticSearch simple_query_string to support fuzzy

I have a record in my ElasticSearch index with the term "cleveland". When I do this search:
"query": {
"multi_match": {
"fields": [
"firstname^3",
"lastname^3",
"home_address",
"home_city"
],
"query": "clevela",
"fuzziness": "AUTO"
}
},
it successfully finds the term. The missing two characters are within the fuzziness threshold. But I'd like to support the extended query syntax of simple_query_string (+, -, phrase search, etc.) So I tried this syntax:
"query": {
"simple_query_string": {
"query": "clevela",
"fields": [
"firstname^3",
"lastname^3",
"home_address",
"home_city"
],
"lenient": true
}
},
and it does not find the term. Fuzziness appears to be turned off. How do I turn it on?
In a simple query string, you need to specify the fuzziness parameter, by adding ~N (N is the max edit distance) after the search term. Modify your search query as
{
"query": {
"simple_query_string": {
"query": "clevela~2", // note this
"fields": [
"firstname^3",
"lastname^3",
"home_address",
"home_city"
],
"lenient": true
}
}
}

Elasticsearch searching across fields with boosting and fuzziness

I am creating an index in elasticsearch and i want the ability to search across multiple fields i.e. have those fields be treated as one big search field. I've done some researching a came across 2 different ways to do this:
The first is with cross_fields multi-match query. This allows for searching across multiple fields as one big field with the ability to boost certain fields. But does not allow for fuzziness to be added.
Using copy_to I can copy fields to an 'all' field so that all the searchable terms are in one big field. This allows for fuzzy search but then does not allow me to boost by specific fields
Is there another cross_fields or search option i'm unaware of that will allow for me to fuzzy search as well as boost by a specific field?
I think you could add fussiness to multi match.
But it will be applied to all fields.
Find an example below with boost and fuzziness
GET /my_index/_search
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "bjorn borg schoenen",
"fields": [
"title^5.0",
"brand^2.0"
],
"type": "best_fields",
"operator": "and",
"fuzziness": "auto"
}
}
]
}
}
}
If you want to be more granular, you can use a boolean query with should and a minimum should match:
{
"query": {
"bool": {
"should": [
{
"match": {
"brand": {
"query": "my query",
"fuzziness": "auto",
"boost": 2
}
}
},
{
"match": {
"title": {
"query": "my query",
"fuzziness": "auto",
"boost": 5
}
}
}
],
"minimum_should_match": 1
}
}
}
And if the query become to complicated, I can suggest you to use a search template to keep integration easy on the app side:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html

Elasticsearch: how to disable scoring on a field?

I am new to Elasticsearch and please forgive me if the answer is obvious.
Here is what I have for the mapping of the field in question:
"condition" : { "type" : "string", "store" : "no", "index": "not_analyzed", "omit_norms" : "true" }
I need search on this field, but I need 100% string match (no stemming, etc.) on a sub-string (blank separated). An example of this field in a document is as follows:
{
"condition": "abc xyz"
}
An example query is:
/_search?q=condition:xyz
Is the above mapping correct? I also used omit_norms (true). Is this a correct thing to do in my case?
How can I disable scoring on this field? Can I do it in mapping? What is the best way of doing it? (Actually I need to disable scoring on more than one. I do have fields that need scoring)
Thanks and regards!
Using omit_norms:true will not take the length of the field into consideration for the scoring, Elasticsearch won't index the norms information. So if you don't want to use scoring that is a good thing to do as it will save you some disk space.
If you're not interested in scoring in your queries use a filtered query:
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": {
"term": {
"condition": "abc xyz"
}
}
}
}
}
}
}
The new syntax for a filtered query is now:
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"term": {
"condition": "abc"
}
}
}
}
}

Resources