Combine two range filters inside a bool query - elasticsearch

In my ES index, documents have two fields, score_min and score_max, which I am trying to boost in a bool query.
I want to boost all documents for which score_min <= expected_score <= score_max is true.
I know that I can put two range queries in the must clause, but that would mean that other documents would get overlooked.
Is there a way to do something like this
..
..
"should": [
...
...
"some_query": {
"and": [
"range": {
"score_min": {
"lte": expected_score
},
},
"range": {
"score_max": {
"gte": expected_score
}
}
"boost": 2
]
}
]

You can do this using the function_score query. One of the added benefits is that your range query can be written as a filter instead, and so take advantage of filter caching:
curl -XGET "http://localhost:9200/_search" -d'
{
"query": {
"function_score": {
"query": {
"match": { "some_field": "foo bar" }
},
"functions": [
{
"boost_factor": 1.2
"filter": {
"bool": {
"must": [
{ "range": { "score_min": { "lte": 10 }}},
{ "range": { "score_max": { "gte": 10 }}}
]
}
}
}
]
}
}
}'
All results matching the query are returned, but any results which additionally match the filter will have their score multiplied by boost_factor.

Related

ElasticSearch - use two range queries to find documents that match either or both of the queries

The index has fields discount_a and discount_b. I want to find documents where either discount_a is "gte": 10 OR discount_b is "gte": 15.
I want the query to find documents that match one or both criteria. I tried putting the range queries in the should, but this also returns documents that do not meet either criteria.
ElasticSearch version is 6.8.
Ideally I want to do something like this, except find documents that match either of the range queries, not necessarily both.
{
"query": {
"bool": {
"must": [
{
"match_all": {}
},
{
"range": {
"discount_a": {
"gte": 10
}
}
},
{
"range": {
"discount_b": {
"gte": 15
}
}
}
],
"filter": [],
"should": [],
"must_not": []
}
},
"from": 0,
"size": 500
}
Here's what I tried in the should
"should": [
{
"range": {
"discount_a": {
"gte": 10
}
}
},
{
"range": {
"discount_b": {
"gte": 15
}
}
}
]
{
"query": {
"bool": {
"should": [
{
"range": {
"discount_a": {
"gte": 10
}
}
},
{
"range": {
"discount_b": {
"gte": 15
}
}
}
]
},
"minimum_should_match": "1"
}
}

Compond query with Elasticsearch

I'm trying to perform a search with the intended criteria being (activationDate in range 1598889600 to 1602051579) or someFlag=true.
Below is the query I tried, but it does not yield any records with someFlag=true (even with a big size, e.g. 5000). My Elasticsearch does have a lot of records with someFlag=true.
There are about 3000 total documents and this query returns around 280 documents.
{
"query": {
"bool": {
"must": [
{
"range": {
"activationDate": {
"gte": 1598889600
}
}
},
{
"range": {
"activationDate": {
"lte": 1602051579
}
}
}
],
"should": {
"match": {
"someFlag": true
}
}
}
},
"from": 1,
"size": 1000
}
Am I missing something?
This should work:
{
"query": {
"bool": {
"filter": [
{
"bool": {
"should": [
{
"range": {
"activationDate": {
"gte": 1598889600,
"lte": 1602051579
}
}
},
{
"term": {
"someFlag": true
}
}
]
}
}
]
}
}
}
In theory this should do the same:
{
"query": {
"bool": {
"should": [
{
"range": {
"activationDate": {
"gte": 1598889600,
"lte": 1602051579
}
}
},
{
"term": {
"someFlag": true
}
}
]
}
}
}
However the first query I've given wraps bool clause within a filter context (so that it does not need to score and query becomes cacheable).
Your bool query might have not worked because you were using match query, not term. match is normally used for text search only.
Replace the must with an should and set minimum_should_match=1 as is is an OR query and you are fine if just one of the ceiterias is met by any record. Next reduce the two range criterias to just one, where you combine gte and lte.

elasticsearch must query combine OR?

I have been trying to use a must query with bool but I am failing to get the results.
In pseudo-SQL:
SELECT * FROM info WHERE (ulevel= '1.3.10' or ulevel= '1.3.6') AND (#timestamp between '2017-06-05T07:00:00.000Z' and '2017-06-05T07:00:00.000Z')
Here is what I have:
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "_all",
"query": "*"
},
"range": {
"#timestamp": {
"from": "2017-06-05T07:00:00.000Z",
"to": "2017-06-05T07:20:00.000Z"
}
},
"bool": {
"should": [
{"term": { "ulevel": "1.3.10"}},
{"term": { "ulevel": "1.3.6"}}
]
}
}
]
}
}
Does anyone have a solution?
Thank you so much.
You can use terms query for the first part and the range query for the second part
GET _search
{
"query": {
"bool": {
"must": [
{
"terms": {
"ulevel": [
"1.3.10",
"1.3.6"
]
}
},
{
"range": {
"#timestamp": {
"gte": "2017-06-05T07:00:00.000Z",
"lte": "2017-06-05T07:20:00.000Z"
}
}
}
]
}
},
"from": 0,
"size": 20
}
Some Notes :
Filters documents that have fields that match any of the provided terms (not analyzed)
Also you can use some date spesific formulation with rage filter. Please check the range query page https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html#ranges-on-dates more information.
Update:
Added from and size for comment question.

Give higher priority to specific ranges in elasticsearch

Here is a sample document from my index
{
"name" : "Neil Buckinson",
"insuranceType" : "personal",
"premiumAmount": 4000,
"age": 36
}
I want to give the documents with premium amount 3500 to 4500 more priority than others. How can I do that in elasticsearch?
I would say a better approach would be function score query with filter functions -
{
"query": {
"function_score": {
"functions": [
{
"weight": 100,
"filter": {
"range": {
"premiumAmount": {
"gte": 3500,
"lte": 4500
}
}
}
}
]
}
}
}
That's quite simple. Just use Bool Query and add your condition in should clause.
The bool query takes a more-matches-is-better approach, so the score
from each matching must or should clause will be added together to
provide the final _score for each document.
GET /index/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"should": [
{
"range": {
"premiumAmount": {
"gte": 3500,
"lte": 4500
},
"boost": 2
}
}
]
}
}
}
Just place your current query in must clause instead of match_all.
should means that this condition is optional, but if it matches your criterion, it will boost your document
That's what exactly you're looking for.

search for a certain text between within a range of a certain timestamp with Elasticsearch

I have worked with Elasticsearch and have done some research on the Internet how to query data with a certain text and how to query data within a range of timestamp, using Elasticsearch PHP Client API. Now I would like to combine these two queries in one. Lets say search for a certain text and within a range of a certain timestamp. Can someone please tell me how to do that using Elasticsearch PHP Client API? Thanks in advanced! I have searched on the Internet but still cannot combine these two queries in one :-(
Here is an example of a bool query, the logic here is that the record must fall within a date range and should also contain the text in the textfield field. You could have both query conditions within the must clause.
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [
{
"range": {
"datefield": {
"gte": "from",
"lte": "to"
}
}
}
],
"should": [
{
"match": {
"textfield": {
"query": "Name",
"boost": 10
}
}
}
]
}
}
}
UPDATE - OR MUST HAVE BOTH
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [
{
"range": {
"datefield": {
"gte": "from",
"lte": "to"
}
}
},
{
"match": {
"textfield": {
"query": "Name",
"boost": 10
}
}
}
]
}
}
}

Resources