Elasticsearch how to order by filter query - elasticsearch

i have the following query the result is satisfying but the order of result not according to filter applied.
the order of results should be:
a1.in
a2.in
a3.in
but the results are not ordered by the filters.
my question is how i can order by the results as per the filters applied?
thanks in advance.
Following is the query i am using
post /mycity/_search?_source=meta_description,url,h1tag
{
"query": {
"function_score":{
"query":{
"match_phrase_prefix": {
"meta_description.edgegrm": {
"query": "best restaurant",
"prefix_length": 1,
"max_expansions": 5,
"slop":10,
"minimum_should_match":"75%"
}
}
},
"query":{
"match_phrase_prefix": {
"content.edgegrm": {
"query": "best restaurant",
"prefix_length": 1,
"max_expansions": 5,
"slop":10,
"minimum_should_match":"75%"
}
}
},
"functions":[
{
"filter":{"term": {
"host": "www.a1.in/city"
}},
"weight":100
},
{
"filter":{
"term": {
"host": "www.a2.in/city"
}
},
"weight":50
},
{
"filter":{
"term": {
"host": "www.a3.in/city"
}
},
"weight":25
}
],
"score_mode": "sum"
}
},
"from":0,
"size":100
}

Try setting boost_mode to sum as well.

Related

Why does Elasticsearch score these documents the way it does?

I have a query where I'm trying pull documents out of my index and sort them by a date. Additionally, if the document's ID matches a provided one then I boost that result.
When I run my query I'm noticing that some of the documents with a more recent sort date are not at the top of the results because Elasticsearch is giving them a different score than other documents. As a result my result order is incorrect. I don't see anything in my query that could be affecting the score. Anyone have any idea what's happening?
Here's the query I'm using:
{
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"match": {
"language.keyword": {
"query": "english",
"operator": "OR",
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
"functions": [
{
"filter": {
"match": {
"id": {
"query": "ID1",
"operator": "OR",
"boost": 1
}
}
},
"weight": 10
}
],
"score_mode": "multiply",
"boost_mode": "multiply",
"boost": 1
}
},
"sort": [
{
"_score": {
"order": "desc"
}
},
{
"sortDate": {
"order": "desc"
}
}
]
}

Source filtering an array of objects in ElasticSearch

Here is a document in ElasticSearch
"CompanyId": 5733,
"PartNumber": "W8S038",
"Name_en": "#8 Washer, M4 Compatible, Stainless Steel, Pack of 100",
"ProductId": 90023,
"CompanyName": "Washers Ltd",
"Prices": [
{
"BuyerId": 308,
"Price": 2.42
}
,
{
"BuyerId": 406,
"Price": 2.22
}
]
}
Obviously we can't let on to buyer 308 that buyer 406 is getting a better price. Therefore when buyer 308 is searching I need to remove all of the prices for other buyers.
I'd like to do this by using source filtering. But how?!
(I could exclude Prices and add back in the required price by using a script_field. However, that means that the price is not part of the source document and therefore ReactiveSearch can't see it and therefore can't sort on it.)
Update: here is the query generated by ReactiveSearch to which I need to append the limit on prices:
"query":{
"bool":{
"must":[
{
"bool":{
"must":[
{
"bool":{
"must":[
{
"bool":{
"should":[
{
"multi_match":{
"query":"m4 washer",
"fields":[
"Name_en"
],
"type":"cross_fields",
"operator":"and"
}
},
{
"multi_match":{
"query":"m4 washer",
"fields":[
"Name_en"
],
"type":"phrase_prefix",
"operator":"and"
}
}
],
"minimum_should_match":"1"
}
}
]
}
}
]
}
}
],
"filter": [
{
"nested": {
"path": "Prices",
"query": {
"term": {
"Prices.CompanyId": 1474
}
},
"inner_hits": {}
}
}
]
}
},
"size":10,
"aggs":{
"CompanyName.raw":{
"terms":{
"field":"CompanyName.raw",
"size":1000,
"order":{
"_count":"desc"
}
}
}
},
"_source":{
"excludes":[
"PurchasingViews",
"ContractFilters",
"SearchField*",
"Keywords*",
"Menus*"
]
},
"from":0,
"sort":[
{
"Name_en.raw":{
"order":"asc"
}
}
],
"script_fields":{
"price":{
"script":{
"lang":"painless",
"inline":"if(params['_source']['Prices'] != null){for(p in params['_source']['Prices']){ if(p.CompanyId == 1474) return p.Price; }} return null;"
}
}
}
}
(That bool, must, bool, must, bool, must, bool, should seems rather stupid?)
You need to use the nested inner_hits feature like below.
{
"_source": [
"CompanyId", "PartNumber", "Name_en", "ProductId", "CompanyName"
],
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "Prices",
"query": {
"term": {
"Prices.BuyerId": 308
}
},
"inner_hits": {}
}
}
]
}
}
}
In the output you'll get exactly what you expect, namely all the root-level fields and the matching prices for the given buyer.
UPDATE:
Here is how I would rewrite your query:
{
"query": {
"bool": {
"minimum_should_match": "1",
"should": [
{
"multi_match": {
"query": "m4 washer",
"fields": [
"Name_en"
],
"type": "cross_fields",
"operator": "and"
}
},
{
"multi_match": {
"query": "m4 washer",
"fields": [
"Name_en"
],
"type": "phrase_prefix",
"operator": "and"
}
}
],
"filter": [
{
"nested": {
"path": "Prices",
"query": {
"term": {
"Prices.CompanyId": 1474
}
},
"inner_hits": {}
}
}
]
}
},
"size": 10,
"aggs": {
"CompanyName.raw": {
"terms": {
"field": "CompanyName.raw",
"size": 1000,
"order": {
"_count": "desc"
}
}
}
},
"_source": {
"excludes": [
"PurchasingViews",
"ContractFilters",
"SearchField*",
"Keywords*",
"Menus*",
"Prices"
]
},
"from": 0,
"sort": [
{
"Name_en.raw": {
"order": "asc"
}
}
],
"script_fields": {
"price": {
"script": {
"lang": "painless",
"inline": "if(params['_source']['Prices'] != null){for(p in params['_source']['Prices']){ if(p.CompanyId == 1474) return p.Price; }} return null;"
}
}
}
}

Elastic - Multiple filter query syntax

Hello I have the following query that I am running:
{
"_source": [
"source1",
"source2",
"source3",
"source4",
],
"query": {
"bool": {
"minimum_should_match": 1,
"must": {
"filter": [
{
"term": {
"_type": {
"value": "someval1"
}
}
},
{
"term": {
"_type": {
"value": "someval2"
}
}
}
],
"query_string": {
"analyze_wildcard": "true",
"query": "tesla*",
"rewrite": "scoring_boolean"
}
}
}
},
"size": 50,
"sort": [
"_score"
]
}
That is currently returning:
'"reason":"[bool] malformed query, expected [END_OBJECT] but found [FIELD_NAME]","line":1,"col":343},"status":400}'
Any idea how to use multiple filters on a query? I was able to do it just fine on elastic 2.4 but since OR is now deprecated as well as filtered, I am a bit lost.
Thanks!
The syntax of the query is wrong. filter should not be wrapped into the must statement. It should be in the same level with must. Also bool queries must statement should be an array, not an object. So your query should look like this
{
"_source":[
"source1",
"source2",
"source3",
"source4"
],
"query":{
"bool":{
"minimum_should_match":1,
"must":[
{
"query_string":{
"analyze_wildcard":"true",
"query":"tesla*",
"rewrite":"scoring_boolean"
}
}
],
"filter":{
"bool":{
"should":[
{
"term":{
"_type":{
"value":"someval1"
}
}
},
{
"term":{
"_type":{
"value":"someval2"
}
}
}
]
}
}
}
},
"size":50,
"sort":[
"_score"
]
}
I think your filter is OR, that's why I wrap it inside should

Aggregation, Query Context and filter Context not working in Elasticsearch 5.1

I am facing issue in migrating from elastic search 1.5 to 5.1.
Following is my elastic search - 1.5 Query:
{
"_source":["_id","spotlight"],
"query":{
"filtered":{
"filter":{
"and":[
{"term":{"gender":"female"}},
{"range":{"lastlogindate":{"gte":"2016-10-19 12:39:57"}}}
]
}
}
},
"filter":{
"and":[
{"term":{"maritalstatus":"1"}}
]
},
"sort":[{"member2_dummy7":{"order":"desc"}}],
"size":"0",
"aggs": {
"maritalstatus": {
"filter": {},
"aggs" : {
"filtered_maritalstatus": {"terms":{"field":"maritalstatus","size":5000}}
}
}
}
}
This query is giving me correct doc_count in aggregations. This doc_count is calculated over result set returned by query context and it ignores filter context.
I have written same query in elastic search 5.1:
{
"_source":["_id","spotlight"],
"query":{
"bool":{
"must":[
{"term":{"gender":"female"}},
{"range":{"lastlogindate":{"gte":"2016-10-19 12:39:57"}}}
],
"filter":{
"bool":{
"must":[
{"term":{"maritalstatus":"1"}}
]
}
}
}
},
"sort":[{"member2_dummy7":{"order":"DESC"}}],
"size":"0",
"aggs": {
"maritalstatus": {
"filter": {},
"aggs" : {
"filtered_maritalstatus": {"terms":{"field":"maritalstatus","size":5000}}
}
}
}
}
But in elastic search 5.1, it is returning me wrong doc_count in aggregation. I think it is taking filter in query context and hence, it is returning wrong doc_cout. Can someone tell me correct way to separate query and filter in elastic search 5.1?
Your 1.5 query uses post_filter which you have removed in your 5.1 query.
The equivalent query in ES 5.1 is the following (filtered/filter simply gets replaced as bool/filter and the top-level filter renamed to post_filter):
{
"_source": [
"_id",
"spotlight"
],
"query": {
"bool": {
"filter": [
{
"term": {
"gender": "female"
}
},
{
"range": {
"lastlogindate": {
"gte": "2016-10-19 12:39:57"
}
}
}
]
}
},
"post_filter": {
"term": {
"maritalstatus": "1"
}
},
"sort": [
{
"member2_dummy7": {
"order": "desc"
}
}
],
"size": "0",
"aggs": {
"maritalstatus": {
"filter": {},
"aggs": {
"filtered_maritalstatus": {
"terms": {
"field": "maritalstatus",
"size": 5000
}
}
}
}
}
}

elasticsearch query to search 2 different queries on same fields and get results which have the combination of both queries

I have 2 parts of query
(a) query
(b) context,
I want to make a query to elasticsearch which give me results on (a), this is mandatory, and the results which have (b) should be boosted.
for example
if the query/(a) is "Inflation rates" and context/(b) is "United States" -- the results should give results only on "Inflation rates" and the results with "United States" should be boosted.
I have tried various concepts of elasticsearch like - bool/should/filter/ but the results are not as exepected.
below I am giving the query template that I am using currently. It gives me results in which query and context are not combined, its just gives docs which either match query or context.
I am using ES 2.4.0
{
"template":{
"from":"0",
"size":"10",
"_source": ["*"],
"query":{
"function_score": {
"query":{
"bool":{
"should":[{
"match":{
"display":{
"query": "inflation rate",
"boost": 2
}
}
},
{
"match":{
"attributes.definition": {
"query": "inflation rate",
"boost": 5
}
}
},
{
"match":{
"attributes.topics.name": {
"query": "inflation rate",
"boost": 5
}
}
},
{
"match":{
"attributes.titles": {
"query": "inflation rate",
"boost": 7
}
}
},
{
"match":{
"attributes.definition": {
"query": "United States",
"boost": 4
}
}
},
{
"match":{
"attributes.topics.name": {
"query": "United States",
"boost": 4
}
}
},
{
"match":{
"attributes.titles": {
"query": "United States",
"boost": 4
}
}
}],
"must": [
{
"match":{
"type":"news"
}
}]
}
},
"functions": [{
"gauss": {
"attributes.published_ts": {
"scale": "10d"
}
},
"weight" : 0.1
}]
}
}
}
}
Should be something like this:
e.g.
{
"query": {
"function_score": {
"filter": {
"bool": {
"must": [{ //here can be should, must etc ... This is your first condition.
"match": {
"attributes.definition": {
"query": "inflation rate",
"boost": 5
}
}
}, {
"match": {
"attributes.topics.name": {
"query": "inflation rate",
"boost": 7
}
}
}]
}
},
"functions": [{ //This is your second condition. Just to give more relevance to the topics with United States.
"filter": {
"term": {
"attributes.topics.name": "United States"
}
},
"weight": 3
}, {
"field_value_factor": {
"field": "views",
"modifier": "log1p"
}
}],
"score_mode": "sum"
}
}
}
Is just an example, adapt it to your own requirements.

Resources