Elasticsearch as a solution for automapping different data - elasticsearch

This is a tricky one.
I'm currently working in a travel agency that needs to map its hotels to other agencies hotels. So let's say that we got an hotel like this one:
Code123, Hotel name 123, street 123, postcode132, country123
And we want to map it to other hotel that is:
ACode123, Hotel 123 name, st 123, pc132, country123
Regarding this, I want to ask two questions:
Is elasticsearch a good solution for this case? So far, I've gotten some good results thanks to elasticsearch nice features regarding search but I've also gotten some misleading matches (for instance, when having long addresses that should match with short addresses).
The other one is, if it's a good solution, which approach should I take?
To give you more context, this is what I got so far:
{
"query": {
"bool": {
"must": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"query_string": {
"default_field": "name",
"query": "Holiday~ Inn~ Express~ Tianjin~ ",
"fuzzy_min_sim": 0.9
}
}
]
}
}
],
"should": [
{
"filtered": {
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "Holiday Inn Express Tianjin",
"boost": 1
}
}
},
{
"query_string": {
"default_field": "country",
"query": "CHINA~ ",
"fuzzy_min_sim": 0.9
}
}
],
"should": [
{
"wildcard": {
"nameTerm": {
"wildcard": "*Holiday* Inn*",
"boost": 1
}
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": "2000m",
"coordinates": {
"lon": 117.1852,
"lat": 39.12841
}
}
}
}
}
]
}
}
],
"should": [
{
"filtered": {
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "Holiday Inn Express Tianjin",
"boost": 1
}
}
},
{
"query_string": {
"default_field": "country",
"query": "CHINA~ ",
"fuzzy_min_sim": 0.9
}
}
],
"should": [
{
"wildcard": {
"nameTerm": {
"wildcard": "*Holiday* Inn* Express*",
"boost": 1.5
}
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": "1500m",
"coordinates": {
"lon": 117.1852,
"lat": 39.12841
}
}
}
}
}
]
}
}
],
"should": [
{
"filtered": {
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "Holiday Inn Express Tianjin",
"boost": 1
}
}
},
{
"query_string": {
"default_field": "country",
"query": "CHINA~ ",
"fuzzy_min_sim": 0.9
}
}
],
"should": [
{
"query_string": {
"default_field": "addressNoNumbers",
"query": " ZHONGSHAN ROAD HEBEI DISTRICT",
"fuzzy_min_sim": 0.8
}
},
{
"match": {
"addressNumbers": {
"query": "288",
"boost": 1.5
}
}
},
{
"term": {
"nameTerm": {
"value": "Holiday Inn Express Tianjin",
"boost": 2
}
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": "1000m",
"coordinates": {
"lon": 117.1852,
"lat": 39.12841
}
}
}
}
}
]
}
}
],
"should": [
{
"filtered": {
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "Holiday Inn Express Tianjin",
"boost": 1
}
}
}
],
"should": [
{
"match": {
"addressNumbers": {
"query": "288",
"boost": 1.5
}
}
},
{
"wildcard": {
"addressTerm": {
"wildcard": "*ZHONGSHAN* ROAD*",
"boost": 1
}
}
},
{
"term": {
"nameTerm": {
"value": "Holiday Inn Express Tianjin",
"boost": 2
}
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": "500m",
"coordinates": {
"lon": 117.1852,
"lat": 39.12841
}
}
}
}
}
]
}
}
],
"should": [
{
"filtered": {
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "Holiday Inn Express Tianjin",
"boost": 1
}
}
}
],
"should": [
{
"match": {
"addressNumbers": {
"query": "288",
"boost": 1.5
}
}
},
{
"wildcard": {
"addressTerm": {
"wildcard": "*ZHONGSHAN* ROAD*",
"boost": 1
}
}
},
{
"term": {
"nameTerm": {
"value": "Holiday Inn Express Tianjin",
"boost": 2
}
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": "300m",
"coordinates": {
"lon": 117.1852,
"lat": 39.12841
}
}
}
}
}
]
}
}
],
"should": [
{
"filtered": {
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "Holiday Inn Express Tianjin",
"boost": 1
}
}
}
],
"should": [
{
"match": {
"addressNumbers": {
"query": "288",
"boost": 1.5
}
}
},
{
"wildcard": {
"addressTerm": {
"wildcard": "*ZHONGSHAN* ROAD*",
"boost": 1
}
}
},
{
"term": {
"nameTerm": {
"value": "Holiday Inn Express Tianjin",
"boost": 2
}
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": "100m",
"coordinates": {
"lon": 117.1852,
"lat": 39.12841
}
}
}
}
}
]
}
}
}
So lots of nesting, that work quite well when I'm getting all the fields but not that much when I'm missing coordinate.
But anyway, my main concern is if I should go with elasticsearch or not (and which could be the alternative!)
Thanks in advance!

Related

Elasticsearch how to set different value with different scores for the same filed?

I have different type_id in an ES index , and want to give different value type_id different scores to make some type search result rank is higher .
My query is
{
"query":{
"bool":{
"must":[
{"terms":{"type_id":[9,10]}}
],
"should":[
{"match":{ "display_name":{"query":"keyword","boost":10}}},
{"match":{ "description":{"query":"keyword","boost":2}}}
]
}
}
}
I want to make type_id 9 match scores is higher than type_id 10 when display_name and description is same .
Please guide me in this problem.
Thanks.
You can group your queries like below and use boost to give more weightage to certain ids.
{
"query": {
"bool": {
"must": [
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"term": {
"type_id": {
"value": 9,
"boost": 2
}
}
},
{
"term": {
"type_id": {
"value": 10,
"boost": 1
}
}
}
]
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"match": {
"display_name": {
"query": "keyword",
"boost": 10
}
}
},
{
"match": {
"description": {
"query": "keyword",
"boost": 2
}
}
}
]
}
}
]
}
}
}
Edit: For query in comment , you can use function_score
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"function_score": {
"query": {
"bool": {
"must": [
{
"term": {
"type_id": {
"value": 9
}
}
}
],
"minimum_should_match": 1,
"should": [
{
"match": {
"display_name": {
"query": "keyword"
}
}
},
{
"match": {
"description": {
"query": "keyword"
}
}
}
]
}
},
"boost": "5"
}
},
{
"function_score": {
"query": {
"bool": {
"must": [
{
"term": {
"type_id": {
"value": 10
}
}
}
],
"minimum_should_match": 1,
"should": [
{
"match": {
"display_name": {
"query": "keyword"
}
}
},
{
"match": {
"description": {
"query": "keyword"
}
}
}
]
}
},
"boost": "4"
}
}
]
}
}
}

Search by child product when search by sku in elastic search query

I have some products below
Id Name SKU isParent
1 A 100 True
2 A1 101 False
3 A2 102 False
4 A3 103 False
5 A4 104 False
6 B 105 True
7 B1 106 False
8 B2 107 False
I have query to find the product by name,SKU.
I want to exclude the product which is IsParent is false when try to search by name but when its exact search by sku then all product need to be search. How to do it?
Search by name is working fine with excluding isParent false products.
My elastic query as below
{
"min_score": 810,
"query": {
"bool": {
"must": [
{
"term": {
"Published": {
"value": "true"
}
}
},
{
"terms": {
"Stores.Id": [
0,
1
]
}
},
{
"bool": {
"must_not": {
"term": {
"IsParentProduct": "false"
}
}
}
},
{
"bool": {
"should": [
{
"match_phrase": {
"Name": {
"query": "BGEBASIC33",
"boost": 100
}
}
},
{
"match": {
"Name": {
"query": "BGEBASIC33",
"boost": 150
}
}
},
{
"match_phrase": {
"ProductCategories.Name.exact": {
"query": "BGEBASIC33",
"boost": 200
}
}
},
{
"match": {
"ProductCategories.Name.exact": {
"query": "BGEBASIC33",
"boost": 300
}
}
},
{
"match_phrase": {
"ParentCategory.Name": {
"query": "BGEBASIC33",
"boost": 1000
}
}
},
{
"match": {
"ParentCategory.Name": {
"query": "BGEBASIC33",
"boost": 750
}
}
},
{
"match_phrase": {
"ShortDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match": {
"ShortDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match_phrase": {
"FullDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match": {
"FullDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match_phrase": {
"ProductManufacturer.Name.exact": {
"query": "BGEBASIC33",
"boost": 200
}
}
},
{
"match": {
"ProductManufacturer.Name.exact": {
"query": "BGEBASIC33",
"boost": 200
}
}
},
{
"nested": {
"path": "ProductPromoTags",
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match_phrase": {
"ProductPromoTags.Name": {
"query": "BGEBASIC33",
"boost": 100
}
}
},
{
"match": {
"ProductPromoTags.Name": {
"query": "BGEBASIC33",
"boost": 100
}
}
}
]
}
},
{
"bool": {
"should": [
{
"match_phrase": {
"ProductPromoTags.SystemName": {
"query": "BGEBASIC33",
"boost": 100
}
}
},
{
"match": {
"ProductPromoTags.SystemName": {
"query": "BGEBASIC33",
"boost": 100
}
}
}
]
}
}
]
}
}
}
},
{
"match": {
"Sku": {
"query": "BGEBASIC33",
"boost": 500
}
}
},
{
"match_phrase": {
"Sku": {
"query": "BGEBASIC33",
"boost": 100
}
}
},
{
"nested": {
"path": "SpecificationAttributes",
"query": {
"bool": {
"should": [
{
"match_phrase": {
"SpecificationAttributes.SpecificationAttributeOptions.Name.exact": {
"query": "BGEBASIC33",
"boost": 80
}
}
},
{
"match": {
"SpecificationAttributes.SpecificationAttributeOptions.Name.exact": {
"query": "BGEBASIC33",
"boost": 100
}
}
}
]
}
}
}
}
]
}
}
]
}
},
"from": 0,
"size": 32,
"aggs": {
"PriceRanges": {
"range": {
"field": "FinalPrice",
"ranges": [
{
"from": "0",
"to": "100"
},
{
"from": "101",
"to": "998"
},
{
"from": "999",
"to": "1999"
},
{
"from": "2000",
"to": "2999"
},
{
"from": "3000"
}
]
}
},
"ProductCategoryCustomURL": {
"terms": {
"field": "ProductCategories.CustomURL",
"size": 100
}
},
"ProductManufacturer": {
"terms": {
"field": "ProductManufacturer.Name",
"size": 100
}
},
"SpecificationAttributesfiltered": {
"filter": {
"bool": {
"must": [
]
}
},
"aggs": {
"SpecificationAttributes": {
"nested": {
"path": "SpecificationAttributes"
},
"aggs": {
"Spec_group": {
"terms": {
"field": "SpecificationAttributes.Name",
"size": 100
},
"aggs": {
"Opctions": {
"terms": {
"field": "SpecificationAttributes.SpecificationAttributeOptions.Name",
"size": 100
}
}
}
}
}
}
}
},
"SpecificationAttributesFirstFiltered": {
"filter": {
"bool": {
"must": [
]
}
},
"aggs": {
"SpecificationAttributes": {
"nested": {
"path": "SpecificationAttributes"
},
"aggs": {
"Spec_group": {
"terms": {
"field": "SpecificationAttributes.Name",
"size": 100
},
"aggs": {
"Opctions": {
"terms": {
"field": "SpecificationAttributes.SpecificationAttributeOptions.Name",
"size": 100
}
}
}
}
}
}
}
}
}
}
Main image is parent product.
After image you can see the three round image and sequre box that are separate products that connect with main image product. Child products haveing property "IsChildProduct" that is set as true if its child.
I want to exclude the child products in search as separate product that is working fine in my query. but if user want to search by child product sku,name etc then my query return emty result.
Let me know what should I do to make this working.
You should share the query you have so far, but here is my take. Basically, one of the should clause must match, either by Name with isParent: false or just by SKU:
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must_not": {
"term": {
"isParent": false
}
},
"must": [
{
"match": {
"Name": "xyz_search_term"
}
}
]
}
},
{
"term": {
"Sku": "xyz_search_term"
}
}
]
}
}
}
UPDATE:
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must_not": {
"term": {
"isParent": false
}
},
"must": [
{
"match_phrase": {
"Name": {
"query": "BGEBASIC33",
"boost": 100
}
}
},
{
"match": {
"Name": {
"query": "BGEBASIC33",
"boost": 150
}
}
},
{
"match_phrase": {
"ProductCategories.Name.exact": {
"query": "BGEBASIC33",
"boost": 200
}
}
},
{
"match": {
"ProductCategories.Name.exact": {
"query": "BGEBASIC33",
"boost": 300
}
}
},
{
"match_phrase": {
"ParentCategory.Name": {
"query": "BGEBASIC33",
"boost": 1000
}
}
},
{
"match": {
"ParentCategory.Name": {
"query": "BGEBASIC33",
"boost": 750
}
}
},
{
"match_phrase": {
"ShortDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match": {
"ShortDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match_phrase": {
"FullDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match": {
"FullDescription": {
"query": "BGEBASIC33",
"boost": 5
}
}
},
{
"match_phrase": {
"ProductManufacturer.Name.exact": {
"query": "BGEBASIC33",
"boost": 200
}
}
},
{
"match": {
"ProductManufacturer.Name.exact": {
"query": "BGEBASIC33",
"boost": 200
}
}
},
{
"nested": {
"path": "ProductPromoTags",
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match_phrase": {
"ProductPromoTags.Name": {
"query": "BGEBASIC33",
"boost": 100
}
}
},
{
"match": {
"ProductPromoTags.Name": {
"query": "BGEBASIC33",
"boost": 100
}
}
}
]
}
},
{
"bool": {
"should": [
{
"match_phrase": {
"ProductPromoTags.SystemName": {
"query": "BGEBASIC33",
"boost": 100
}
}
},
{
"match": {
"ProductPromoTags.SystemName": {
"query": "BGEBASIC33",
"boost": 100
}
}
}
]
}
}
]
}
}
}
},
{
"nested": {
"path": "SpecificationAttributes",
"query": {
"bool": {
"should": [
{
"match_phrase": {
"SpecificationAttributes.SpecificationAttributeOptions.Name.exact": {
"query": "BGEBASIC33",
"boost": 80
}
}
},
{
"match": {
"SpecificationAttributes.SpecificationAttributeOptions.Name.exact": {
"query": "BGEBASIC33",
"boost": 100
}
}
}
]
}
}
}
}
]
}
},
{
"bool": {
"should": [
{
"match": {
"Sku": {
"query": "BGEBASIC33",
"boost": 500
}
}
},
{
"match_phrase": {
"Sku": {
"query": "BGEBASIC33",
"boost": 100
}
}
}
]
}
}
]
}
}
}

Weighted search on one field and a normal search on other field

I am trying to perform a search by matching the search query to either the tag or the name of the doc, I also have a filter on the top, so I do have to use must.
Here is what I have been trying,
{
"query": {
"bool": {
"filter": {
"term": {
"type.primary": "audio"
}
},
"must": [
{
"nested": {
"path": "tags",
"score_mode": "sum",
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"match": {
"tags.tag": "big"
}
}
]
}
},
"field_value_factor": {
"field": "tags.weight"
},
"boost_mode": "multiply",
"boost": 10
}
}
}
},
{
"bool": {
"must": [
{
"multi_match": {
"query": "big",
"fields": [
"name"
],
"type": "phrase_prefix"
}
}
]
}
}
]
}
}
}
This just results in empty.
If I use should instead of must the query works fine, but it gives me all results with the filter of type.primary: audio.
I am pretty sure there is some other way to search for the name field. Thanks.
You're almost there! In your must, you declare that both tags and name has to hit. Try the following:
GET /_search
{
"query": {
"bool": {
"filter": {
"term": {
"type.primary": "audio"
}
},
"must": [
{
"bool": {
"should": [
{
"nested": {
"path": "tags",
"score_mode": "sum",
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"match": {
"tags.tag": "big"
}
}
]
}
},
"field_value_factor": {
"field": "tags.weight"
},
"boost_mode": "multiply",
"boost": 10
}
}
}
},
{
"multi_match": {
"query": "big",
"fields": [
"name"
],
"type": "phrase_prefix"
}
}
]
}
}
]
}
}
}

Elasticsearch - boosting specific documents in every search

I'm very new to Elasticsearch. I'm using it to filtering and also boosting some fields at query time. This is the code part for boosting and filtering:
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"multi_match": {
"type": "best_fields",
"query": "exampleKeyword",
"fields": [
"exampleField1^0",
"exampleField2^50",
"exampleField3^10",
"exampleField4^10",
"exampleField5^5"
],
"boost": 50
}
}]
}
}
],
"filter": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"term": {
"bla": {
"value": ""
}
}
}
]
}
}, {
"term": {
"active": {
"value": "true"
}
}
},
{
"range": {
"closingDate": {
"gte": "201710310000",
"lte": "999912312359"
}
}
},
Now I want to boost some specific documents. I'll give an array of integers for example Field6 and if my search results contain the elements of the array, these documents should get boosted with, I dont know, 100 to my scale.
How can I do this? Finally I dont want to expand the result set. Just want to boost more the desired ids if results contain these ids.
Using function_score you can do something around these lines:
{
"query": {
"bool": {
"must": [
{
"function_score": {
"query": {
"bool": {
"should": [
{
"multi_match": {
"type": "best_fields",
"query": "bla",
"fields": [
"exampleField1^0",
"exampleField2^50",
"exampleField3^10",
"exampleField4^10",
"exampleField5^5"
],
"boost": 50
}
}
]
}
},
"functions": [
{
"filter": {
"ids": {
"values": [
1,
5
]
}
},
"weight": 10
}
],
"score_mode": "max",
"boost_mode": "multiply"
}
}
],
"filter": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"term": {
"bla": {
"value": ""
}
}
}
]
}
},
{
"term": {
"active": {
"value": "true"
}
}
},
{
"range": {
"closingDate": {
"gte": "201710310000",
"lte": "999912312359"
}
}
}
]
}
}
]
}
}
}

Rescoring and Sorting of documents

My goal is to write a query which would rescore documents based on value of a field in the document. To achieve this I was using a rescore query and then sorting the results. However, an explain on the query shows me that the sorting of the documents is done based on the previously computed score and not the new one.
I saw the following which explains that I couldn't use rescore and sort together.
"Sometimes we want to show results, where the ordering of the first documents on the page is affected by the additional rules. Unfortunately this cannot be achieved by the rescore functionality. The first idea points to window_size parameter, but this parameter in fact is not connected with the first documents on the result list but with number of results returned on every shard. In addition window_size cannot be less than page size. (If it is less, ElasticSearch silently use page size). Also, one very important thing – rescoring cannot be combined with sorting, because sorting is done after changes introduced by rescoring."
http://elasticsearchserverbook.com/elasticsearch-0-90-using-rescore/
My query is:
{
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{
"constant_score": {
"query": {
"match": {
"question": {
"query": "diabetes"
}
}
},
"boost": 1
}
},
{
"dis_max": {
"queries": [
{
"constant_score": {
"query": {
"match": {
"question": {
"query": "diabetes"
}
}
},
"boost": 0.01
}
},
{
"constant_score": {
"query": {
"match": {
"answer_text": {
"query": "diabetes"
}
}
},
"boost": 0.0001
}
}
]
}
},
{
"dis_max": {
"queries": [
{
"constant_score": {
"query": {
"match_phrase": {
"question_phrase": {
"query": "what is diabetes",
"slop": 0
}
}
},
"boost": 100
}
},
{
"constant_score": {
"query": {
"match_phrase": {
"question_phrase": {
"query": "what is diabetes",
"slop": 1
}
}
},
"boost": 50
}
},
{
"constant_score": {
"query": {
"match_phrase": {
"question_phrase": {
"query": "what is diabetes",
"slop": 2
}
}
},
"boost": 33
}
},
{
"constant_score": {
"query": {
"match_phrase": {
"question_phrase": {
"query": "what is diabetes",
"slop": 3
}
}
},
"boost": 25
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "question_group_four",
"query": "what__is__diabetes"
}
},
"boost": 0.1
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "question_group_five",
"query": "what__is__diabetes"
}
},
"boost": 0.15
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_no_synonyms_20",
"query": "what__is__diabetes"
}
},
"boost": 35
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_no_synonyms_15",
"query": "what__is__diabetes"
}
},
"boost": 25
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_no_synonyms_10",
"query": "what__is__diabetes"
}
},
"boost": 15
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_20",
"query": "what__is__diabetes"
}
},
"boost": 28
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_15",
"query": "what__is__diabetes"
}
},
"boost": 16
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_10",
"query": "what__is__diabetes"
}
},
"boost": 13
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_05",
"query": "what__is__diabetes"
}
},
"boost": 4
}
}
]
}
},
{
"dis_max": {
"queries": [
{
"constant_score": {
"query": {
"query_string": {
"default_field": "question_group_four",
"query": "diabetes"
}
},
"boost": 0.1
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "question_group_five",
"query": "diabetes"
}
},
"boost": 0.15
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_no_synonyms_20",
"query": "diabetes"
}
},
"boost": 35
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_no_synonyms_15",
"query": "diabetes"
}
},
"boost": 25
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_no_synonyms_10",
"query": "diabetes"
}
},
"boost": 15
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_20",
"query": "diabetes"
}
},
"boost": 28
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_15",
"query": "diabetes"
}
},
"boost": 16
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_10",
"query": "diabetes"
}
},
"boost": 13
}
},
{
"constant_score": {
"query": {
"query_string": {
"default_field": "concept_words_05",
"query": "diabetes"
}
},
"boost": 4
}
}
]
}
}
],
"disable_coord": true
}
},
"filter": {
"and": [
{
"term": {
"posted_by_expert": false
}
},
{
"term": {
"tip_question": false
}
},
{
"term": {
"show_in_work_queue": true
}
},
{
"range": {
"verified_answers_count": {
"gt": 0
}
}
}
]
}
}
},
"rescore": {
"window_size": 100,
"query": {
"rescore_query": {
"function_score": {
"functions": [
{
"script_score": {
"script": "_score * _source.concierge_boost"
}
}
]
}
}
}
},
"sort": [
"_score",
{
"count_words_with_high_concepts": {
"order": "asc"
}
},
{
"popularity": {
"order": "desc"
}
},
{
"length": {
"order": "asc"
}
}
],
"fields": [],
"size": 10,
"from": 0
}
Any help highly appreciated !
This is not possible, indeed. But this has been discussed and decided is not worth implementing it at the moment. The discussion on github, though, reveals the difficulty about this - documents need to be sorted, top 100 (in your case) chosen, then a rescore is applied and then they are, again, sorted. I suggest reading the comments in that github issue, especially the ones from simonw. The issue is still open but it doesn't seem it will be implemented soon, if it will at all.
Regarding your sorting after another level of scoring, I understand the need to rescore only few documents, but it seems is not possible. What if you wrap your query in another function_score where you define a script_score function to compute the final score? Something like this:
{
"query": {
"function_score": {
"query": {
.......
},
"functions": [
{
"script_score": {
"script": "doc['concierge_boost'].value"
}
}
]
}
},
"sort": [
"_score",
{
"count_words_with_high_concepts": {
"order": "asc"
}
},
{
"popularity": {
"order": "desc"
}
},
{
"length": {
"order": "asc"
}
}
],
"fields": [],
"size": 10,
"from": 0
}

Resources