elasticsearch : boosting documents in has_parent query - elasticsearch

Is there a way to boost the docs that "come" from the has_parent query ?
{
"query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"multi_match": {
"fields": ["name^3", "tags^2", "content"],
"query": "xx"
}
},
{
"has_parent": {
"type": "theparent",
"query": {
"multi_match": {
"type": "best_fields",
"fields": ["name^5", "content"],
"query": "xx"
}
}
}
},
{
"has_child": {
"type": "thechild",
"query": {
"multi_match": {
"fields": ["name^3","content"],
"query": "xx"
}
}
}
}
]
}
},
"score_mode": "sum",
"functions": [
{
"linear": {
"date": {
"origin": "2014-08-29",
"scale": "700d",
"decay": 0.6
}
}
}
]
}
}
More exactly, I would like to boost those docs only when the query matches the name field of the parent
(I haven't found a way to refer to a parent field in the functions i.e. theparent._source.name ~= "xx")

According to the sources from Github (see line 104), the boost parameter is allowed within a has_parent query.
Based on this attribute, you can boost specifically the should clause containing the has_parent query. In your case, the result would be :
...
{
"has_parent": {
"type": "theparent",
"query": {
"multi_match": {
"type": "best_fields",
"fields": ["name^5", "content"],
"query": "xx"
}
},
"boost": 5
}
}
...
I don't know if it can help you, but you will find more insights about boosting query clauses here.

Related

Search-as-you-type inside arrays

I am trying to implement a search-as-you-type query inside an array.
This is the structure of the documents:
{
"guid": "6f954d53-df57-47e3-ae9e-cb445bd566d3",
"labels":
[
{
"name": "London",
"lang": "en"
},
{
"name": "Llundain",
"lang": "cy"
},
{
"name": "Lunnainn",
"lang": "gd"
}
]
}
and up to now this is what I came with:
{
"query": {
"multi_match": {
"fields": ["labels.name"],
"query": name,
"type": "phrase_prefix"
}
}
which works exactly as requested.
The problem is that I would like to search also by language.
What I tried is:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": ["labels.name"],
"query": "london",
"type": "phrase_prefix"
}
},
{
"term": {
"labels.lang": "gd"
}
}
]
}
}
}
but these queries act on separate values of the array.
So, for example, I would like to search only Welsh language (cy). That means that my query that contains the city name should match only values that have "cy" on the "lang" tag.
How do I write this kind of query?
Internally, ElasticSearch flattens nested JSON objects, so it can't correlate the lang and name of a specific element in the labels array. If you want this kind of correlation, you'll need to index your documents differently.
The usual way to do this is to use the nested data type with a matching nested query.
The query would end up looking something like this:
{
"query": {
"nested": {
"path": "labels",
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": ["labels.name"],
"query": "london",
"type": "phrase_prefix"
}
},
{
"term": {
"labels.lang": "gd"
}
}
]
}
}
}
}
}
But note that you'll need to also specify nested mappings for your labels, e.g.:
"properties": {
"labels": {
"type": "nested",
"properties": {
"name": {
"type": "text"
/* you might want to add other mapping-related configuration here */
},
"lang": {
"type": "keyword"
}
}
}
}
Other ways to do this include:
Indexing each label as a separate document, repeating the guid field
Using parent/child documents
You should use Nested datatype in mapping instead of Object datatype. For detail explanation refer this:
https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html
So, you should define mapping of your field something like this:
{
"properties": {
"labels": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"lang": {
"type": "keyword"
}
}
}
}
}
After this you could query using Nested Query as:
{
"query": {
"nested": {
"path": "labels",
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": ["labels.name"],
"query": "london",
"type": "phrase_prefix"
}
},
{
"term": {
"labels.lang": "gd"
}
}
]
}
}
}
}
}

elastic search phase_prefix query not working for first letter of second word

The following query returns correct document (with movie_name = "star wars") for query = "s", "st", "sta","star", "star wa", "star wars" but not for "star w" returns 0 results.
This happens will all documents and queries, so want to know how to fix this and if there are any other alternatives for the same.
I am using elastic search 1.7. Thanks a lot in advance !
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"constant_score": {
"query": {
"multi_match": {
"query": "star w",
"type": "phrase_prefix",
"fields": [
"movie_name",
"movie_tags"
]
}
},
"boost": 2
}
},
{
"constant_score": {
"query": {
"nested": {
"path": "movie",
"query": {
"nested": {
"path": "movie.cast",
"query": {
"match": {
"movie.cast.name": {
"query": "star w",
"type": "phrase_prefix"
}
}
}
}
}
}
},
"boost": 1
}
}
],....

Elastic : search two terms, one on _all, other one on a field

I would like to mix a search on a whole document (eg "developer") and a search on some field for another term (eg "php").
I can do each search separately but I can't mix them.
Here my example (simplified to show only my issue) :
{
"query": {
"function_score": {
"query": {
"match": {
"_all": "developer"
},
"multi_match": {
"query": "php",
"fields": [
"skills.description",
"skills.description",
"skills.details"
],
"operator": "or",
"type": "most_fields"
}
}
}
}
If I run this example I have an error :
Parse Failure [Failed to parse source
Is there a way to search on both _all and specific fields with two terms?
Thanks.
Yes, you're almost there, you need to combine them into a bool/must query:
{
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"match": {
"_all": "developer"
}
},
{
"multi_match": {
"query": "php",
"fields": [
"skills.description",
"skills.description",
"skills.details"
],
"operator": "or",
"type": "most_fields"
}
}
]
}
}
}
}
}

Multi_match and match queries together

I have the following queries in elastic search :
{
"query": {
"multi_match": {
"query": "bluefin bat",
"type": "phrase",
"fields": [
"title^5",
"body.value"
]
}
},
"highlight": {
"fields": {
"body.value": {
"number_of_fragments": 3
}
}
},
"fields": [
"title",
"id"
]
}
I have tried using "dis_max" but then two of my fields have to be searched for the same query.
The remaining match query has a different query text.
The remaining match query is like this:
{
"query": {
"match": {
"ingredients": "key1, key2",
"analyzer": "keyword_analyzer"
}
}
}
How can I integrate these two queries without using dis_max for joining.
I figured out the answer. multi_match internally applies :
"dis_max"
Hence, you cannot apply dis_max with multi_match.
But what I could do is I could apply bool query to solve this type of problem.
I could apply should which actually translates to OR boolean value or I could apply must which is equivalent to AND.
So this is how I modified my query :
{
"query": {
"bool":{
"should": [
{"multi_match":
{"query": "SOME_QUERY",
"type": "phrase",
"fields": ["title^5","body"]
}
},
{
"match":{
"labels" :{
"query": "SOME_QUERY",
"analyzer": "keyword_analyzer"
}
}
},
{
"match":{
"displayName" :{
"query": "SOME_QUERY",
"fuzziness": "AUTO"
}
}
}
],
"minimum_number_should_match": "50%"
}
},
"fields": ["title","id","labels","displayName","username"],
"highlight": {
"fields": {
"body.storage.value": {
"number_of_fragments": 3}
}
}
}
I hope this helps someone in future.

How to filter using any of the full text queries?

I've tried numerous ways to filter using a full text query, but to no avail.
Here's what I've attempted:
{
"_source": "_id",
"query": {
"filtered": {
"multi_match": {
"query": "test search query",
"fields": ["title"]
},
"filter": {
"term": {"user_id": "1"}
}
}
}
}
The filtered query takes a filter and a query, you're missing a query part which wraps your multi_match:
{
"_source": "_id",
"query": {
"filtered": {
"query": { <-- add this
"multi_match": {
"query": "test search query",
"fields": ["title"]
}
},
"filter": {
"term": {"user_id": "1"}
}
}
}
}

Resources