Elastic Search search for all fields and boost exact match - elasticsearch

I'm very new to elastic search, how do I write a query which search for a keyword (ie. test keyword) in all fields in the document, and boost for
exact match for this keyword phrase in all fields.
occurrences for certain fields (which I have boosted 5 for A, 3 for B and 1 for C)
I see some documentation on match_phrase, but it doesn't seem to support multiple fields.
{
"query": {
"multi_match": {
"query": "test keyword",
"fields": ["A^5", "B^3", "C^1"]
}
}
}

If you want an exact match for the keyword phrase in all fields along with boost then try out this below search query where the multi-match query is used with type phrase parameter :
Adding a working example with index data, search query, and search result
Index data:
{
"A":"test keyword",
"B":"a",
"C":"c"
}
{
"A":"a",
"B":"test keyword",
"C":"c"
}
{
"A":"a",
"B":"b",
"C":"test keyword"
}
Search Query:
{
"query": {
"bool": {
"should": [
{
"multi_match": {
"query": "test keyword",
"fields": [
"A^5",
"B^3",
"C^1"
],
"type":"phrase" <-- note this
}
}
]
}
}
}
Search Result:
"hits": [
{
"_index": "stof_64266554",
"_type": "_doc",
"_id": "1",
"_score": 16.285465,
"_source": {
"A": "test keyword",
"B": "a",
"C": "c"
}
},
{
"_index": "stof_64266554",
"_type": "_doc",
"_id": "2",
"_score": 8.142733,
"_source": {
"A": "a",
"B": "test keyword",
"C": "c"
}
},
{
"_index": "stof_64266554",
"_type": "_doc",
"_id": "3",
"_score": 1.6285465,
"_source": {
"A": "a",
"B": "b",
"C": "test keyword"
}
}
]

Related

Which field did find the search query?

ı want to find a field, Which field did find the search query?
this can be any query I am not writing a specific query
for example
ı searching dilo abinin phrase or any word, and found bellow document
{
"name":"dilo abinin",
"surname: "sürücü"
}
ı want to get name keyword
You can use highlighting, to see which field matched your query
Index API
{
"name":"dilo abinin",
"surname": "sürücü"
}
Search Query:
{
"query": {
"query_string": {
"query": "dilo abinin"
}
},
"highlight": {
"fields": {
"*": {}
}
}
}
Search Result:
"hits": [
{
"_index": "65325154",
"_type": "_doc",
"_id": "1",
"_score": 0.5753642,
"_source": {
"name": "dilo abinin",
"surname": "sürücü"
},
"highlight": {
"name": [ // note this
"<em>dilo</em> <em>abinin</em>"
],
"name.keyword": [
"<em>dilo abinin</em>"
]
}
}
]

Elastic search negate phrase and words in simple query string

I'm trying to negate some words and phrases in an Elastic Search request using the simple query string.
This is what I do:
&q=-"the witcher 3"-game-novel
So basically, trying to negate a phrase AND the words after it. But that doesn't seem to work.
If I try to negate the words alone it works.
How can I negate phrases and sentences in a simple query string?
Adding a working example with index data,search query, and search result.
Index Data:
{
"name":"test"
}
{
"name":"game"
}
{
"name":"the witcher"
}
{
"name":"the witcher 3"
}
{
"name":"the"
}
Search Query:
{
"query": {
"simple_query_string" : {
"query": "-(game | novel) -(the witcher 3)",
"fields": ["name"],
"default_operator": "and"
}
}
}
Search Result:
"hits": [
{
"_index": "stof_64133051",
"_type": "_doc",
"_id": "4",
"_score": 2.0,
"_source": {
"name": "the"
}
},
{
"_index": "stof_64133051",
"_type": "_doc",
"_id": "3",
"_score": 2.0,
"_source": {
"name": "the witcher"
}
},
{
"_index": "stof_64133051",
"_type": "_doc",
"_id": "1",
"_score": 2.0,
"_source": {
"name": "test"
}
}
]

ElasticSearch: why it is not possible to get suggest by criteria?

I want to get suggestions from some text for concrete user.
As I understand Elasticsearch provides suggestions based on the whole dictionary(inverted index) that contains all the terms in the index.
So if user1 posts some text then this text can be suggested to user2. Am I right?
Is it possible to add filter by criteria (by user for example) to reduce the set of terms to be suggested?
Yes, that's very much possible, let me show you by an example, which uses the query with filter context:
Index def
{
"mappings": {
"properties": {
"title": {
"type": "text" --> inverted index for storing suggestions on title field
},
"userId" : {
"type" : "keyword" --> like in you example
}
}
}
}
Index sample doc
{
"title" : "foo baz",
"userId" : "katrin"
}
{
"title" : "foo bar",
"userId" : "opster"
}
Search query without userId filter
{
"query": {
"bool": {
"must": {
"match": {
"title": "foo"
}
}
}
}
}
Search results(bring both results)
"hits": [
{
"_index": "so_suggest",
"_type": "_doc",
"_id": "1",
"_score": 0.18232156,
"_source": {
"title": "foo bar",
"userId": "posted" --> note another user
}
},
{
"_index": "so_suggest",
"_type": "_doc",
"_id": "2",
"_score": 0.18232156,
"_source": {
"title": "foo baz",
"userId": "katrin" -> note user
}
}
]
Now lets reduce the suggestion by filtering the docs created by user katrin
Search query
{
"query": {
"bool": {
"must": {
"match": {
"title": "foo"
}
},
"filter": {. --> note filter on userId field
"term": {
"userId": "katrin"
}
}
}
}
}
Search result
"hits": [
{
"_index": "so_suggest",
"_type": "_doc",
"_id": "2",
"_score": 0.18232156,
"_source": {
"title": "foo baz",
"userId": "katrin"
}
}
]

elasticsearch : merge 2 fields from different types in search result

Do you know if we can merge dynamically 2 fields which belong to different types in one unique field
I have an index my_index with 2 types type1 and type2
I am doing a search on those 2 types :
POST /my_index/_search
{
"min_score": 1,
"query": {
"bool": {
"should": [
{
"match": {
"titreType1": {
"query": "boy"
}
}
},
{
"match": {
"titreType2": {
"query": "boy"
}
}
}
]
}
}
}
I will have results from the 2 different types that looks like to:
"hits": [
{
"_index": "my_index",
"_type": "type1",
"_id": "AVo0LhFj8N13TOVDqMo9",
"_score": 13.171456,
"_source": {
"titreType1": "the boy !"
}
},
{
"_index": "my_index",
"_type": "type1",
"_id": "AVo0Lg5X8N13TOVDqMUH",
"_score": 12.986091,
"_source": {
"titreType1": "if i were a boy"
}
},
{
"_index": "my_index",
"_type": "type2",
"_id": "AVo0S-nM8N13TOVDqNPX",
"_score": 12.34135,
"_source": {
"titreType2": "boy are very nasty and it is sad"
}
},
...
]
I would like to have in my result just one column named "title" that display value from titreType1 or titreType2
Do you know how to do this?

Elasticsearch query prefer exact match over partial match on multiple fields

I am doing a free text search on documents with multiple fields. When I perform a search I want the documents that have a perfect match on any of the labels to have a higher scoring. Is there any way I can do this from the query?
For example the documents have two fields called label-a and label-b and when I perform the following multi-match query:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "apple",
"type": "most_fields",
"fields": [
"label-a",
"label-b"
]
}
}
]
}
}
}
I get the following results (only the relevant part):
"hits": [
{
"_index": "salad",
"_type": "fruit",
"_id": "4",
"_score": 0.581694,
"_source": {
"label-a": "apple pie and pizza",
"label-b": "pineapple with apple juice"
}
},
{
"_index": "salad",
"_type": "fruit",
"_id": "2",
"_score": 0.1519148,
"_source": {
"label-a": "grape",
"label-b": "apple"
}
},
{
"_index": "salad",
"_type": "fruit",
"_id": "1",
"_score": 0.038978107,
"_source": {
"label-a": "apple apple apple apple apple apple apple apple apple apple apple apple",
"label-b": "raspberry"
}
},
{
"_index": "salad",
"_type": "fruit",
"_id": "3",
"_score": 0.02250402,
"_source": {
"label-a": "apple pie and pizza",
"label-b": "raspberry"
}
}
]
I want the second document, the one with the value grape for label-a and value apple for label-b, to have the highest score as I am searching for the value apple and one of the labels has that exact value. This should work regardless of which label the exact term appears.
Because Elasticsearch uses tf/idf model for scoring you are getting these results. Try to specify in your index fields "label-a" and "label-b" additionally as not-analyzed(raw) fields. Then rewrite your query someth like this:
{
"query": {
"bool": {
"should": {
"match": {
"label-a.raw": {
"query": "apple",
"boost": 2
}
}
},
"must": [
{
"multi_match": {
"query": "apple",
"type": "most_fields",
"fields": [
"label-a",
"label-b"
]
}
}
]
}
}
}
The should clause will boost documents with exact match and you will probably get them in the first place. Try to play with the boost number and pls check th equery before running. This is just and idea what you can do

Resources