Using multiple Should queries - elasticsearch

I want to get docs that are similar to multiple "groups" but separately. Each group has it's own rules (terms).
When I try to use more than one Should query inside a "bool" I get items that are a mix of both Should's terms.
I want to use 1 query total and not msearch for example.
Can someone please help me with that?
{
"explain": true,
"query": {
"filtered": {
"filter": {
"bool": {
"must_not": [
{
"term": {
"p_id": "123"
}
},
{
"term": {
"p_id": "124"
}
}
]
}
},
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"term": {
"cat": "1"
}
},
{
"term": {
"cat": "2"
}
},
{
"term": {
"keys": "a"
}
},
{
"term": {
"keys": "b"
}
}
]
}
},
{
"bool": {
"minimum_should_match": 1,
"should": [
{
"term": {
"cat": "6"
}
},
{
"term": {
"cat": "7"
}
},
{
"term": {
"keys": "r"
}
},
{
"term": {
"keys": "u"
}
}
]
}
}
]
}
}
}
},
"from": 0,
"size": 3
}

You can try using a terms aggregation on multiple fields with scripting and add a top hits aggregation as a sub-aggregation. Be warned this will be pretty slow. Add this after the query/filter and adjust the size parameter as needed
"aggs": {
"Cat_and_Keys": {
"terms": {
"script": "doc['cat'].values + doc['keys'].values"
},
"aggs":{ "separate_docs": {"top_hits":{"size":1 }} }
}
}

Related

How do i combine different search parameters in an elasticscearch dsl query?

Good day together,
I have a little problem in Elastic/Kibana. In the Kibana Query Language "KQL" it is possible for me to execute a certain query:
car:* AND coun: * AND doc: (bes* OR *rvr*) AND NOT coun: (SIP OR LUK)
I would like to use this as a filter query using Elasticscearch query DSL. Only I don't get the same result. For this I use the boolean operator. My query looks like this:
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "car"
}
},
{
"exists": {
"field": "coun"
}
}
],
"should": [
{
"wildcard": {
"doc.keyword": {
"value": "bes*"
}
}
},
{
"wildcard": {
"doc.keyword": {
"value": "*rvr*"
}
}
}
],
"must_not": [
{
"term": {
"coun.keyword": "SIP"
}
},
{
"term": {
"coun.keyword": "LUK"
}
}
],
"minimum_should_match": 1
}
}
}
Unfortunately, I do not get the same result. My guess is the "should" operator. But I don't know exactly how to adjust the code.
I would be very grateful for any answer! Thanks a lot!
Problem here, that you putting OR outside AND. Just move should clause inside must. Like this
GET _search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "car"
}
},
{
"exists": {
"field": "con"
}
},
{
"bool": {
"should": [
{
"wildcard": {
"doc.keyword": {
"value": "bes*"
}
}
},
{
"wildcard": {
"doc.keyword": {
"value": "*rvr*"
}
}
}
]
}
}
],
"must_not": [
{
"term": {
"coun.keyword": "SIP"
}
},
{
"term": {
"coun.keyword": "LUK"
}
}
],
"minimum_should_match": 1
}
}
}

Elasticsearch Add additional condition if type is different

GET test/_search
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must": [
{
"term": {
"fragmentId": "1"
}
},
{
"term": {
"type": "fragment"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"fragmentId": "1"
}
},
{
"term": {
"type": "cf"
}
},
{
"range" :{
"start": {
"gte": 1,
"lte": 5
}
}
}
]
}
}
]
}
}
}
I am looking for two documents, one which has fragment id = 1, and type = fragment, whereas another where fragment id = 1, type = "cf" and start between 1 and 5.
The above query is doing the job, but I need to write type and fragment id twice. Is there a way I can add range condition only when the type is cf, basically clubbing both bools in one ?
This is the query you're looking for:
{
"query": {
"bool": {
"filter": [
{
"term": {
"fragmentId": "1"
}
}
],
"minimum_should_match": 1,
"should": [
{
"term": {
"type": "fragment"
}
},
{
"bool": {
"filter": [
{
"term": {
"type": "cf"
}
},
{
"range": {
"start": {
"gte": 1,
"lte": 5
}
}
}
]
}
}
]
}
}
}

Is it possible to do this sort in ElasticSearch, without using script_score?

I would like to do this sort with a single ElasticSearch query (without resorting to using script_score):
Objects with region=DE and language=de, sorted by createdDate.
Objects with region=DE and any language, sorted by createdDate.
Objects with any region and language=en, sorted by createdDate.
At first, I thought I could do a function_score query (boost_mode: replace, score_mode: sum) and:
If region=DE and language=de, set score to 300000000000000 + createdDate.
If region=DE and language!=de, set score to 200000000000000 + createdDate.
If region!=DE and language=en, set score to 100000000000000 + createdDate.
I can add the createdDate to the score by using field_value_factor. But I can't find a function_score function to add 300000000000000 to the score if region=DE and language=de.
Is it possible to do this without using script_score?
Here's how to do it:
{
"sort": [
{"_score": "desc"},
{"created_date": "desc"}
],
"query": {
"function_score": {
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"constant_score": {
"filter": {
"bool": {
"must": [
{ "term": { "region": "DE" } },
{ "term": { "language": "de" } }
]
}
},
"boost": 3
}
},
{
"constant_score": {
"filter": {
"bool": {
"must": [
{ "term": { "region": "DE" } },
{ "not": { "term": { "language": "de" } } }
]
}
},
"boost": 2
}
},
{
"constant_score": {
"filter": {
"bool": {
"must": [
{ "not": { "term": { "region": "DE" } } },
{ "term": { "language": "en" } }
]
}
},
"boost": 1
}
}
]
}
}
}
}
}

Elasticsearch must_not filter not works with a big bunch of values

I have the next query that include some filters:
{
"from": 0,
"query": {
"function_score": {
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"idpais": [
115
]
}
},
{
"term": {
"tipo": [
1
]
}
}
],
"must_not": [
{
"term": {
"idregistro": [
5912471,
3433876,
9814443,
11703069,
6333176,
8288242,
9924922,
6677850,
11852501,
12530205,
4703469,
12776479,
12287659,
11823679,
12456304,
12777457,
10977614,
...
]
}
}
]
}
},
"query": {
"bool": {
"should": [
{
"match_phrase": {
"area": "Coordinator"
}
},
{
"match_phrase": {
"company": {
"boost": 5,
"query": "IBM"
}
}
},
{
"match_phrase": {
"topic": "IT and internet stuff"
}
},
{
"match_phrase": {
"institution": {
"boost": 5,
"query": "University of my city"
}
}
}
]
}
}
}
},
"script_score": {
"params": {
"idpais": 115,
"idprovincia": 0,
"relationships": []
},
"script_id": "ScoreUsuarios"
}
}
},
"size": 24,
"sort": [
{
"_script": {
"order": "desc",
"script_id": "SortUsuarios",
"type": "number"
}
}
]
}
The must_not filter has a big bunch of values to exclude (around 200 values), but it looks like elasticsearch ignores those values and it includes on the result set. If I try to set only a few values (10 to 20 values) then elasticsearch applies the must_not filter.
Exists some restriction a bout the amount of values in the filters? Exists some way to remove a big amount of results from the query?
terms query is used for passing a list of values not term query.You have to use it like below in your must filter.
{
"query": {
"terms": {
"field_name": [
"VALUE1",
"VALUE2"
]
}
}
}

ElasticSearch ignoring sort when filtered

ElasticSearch Version: 0.90.1, JVM: 1.6.0_51(20.51-b01-457)
I'm trying to do two things with my ElasticSearch query: 1) filter the results based on a boolean (searchable) and "open_date < tomorrow" and 2) two sort by the field "open_date" DESC
This produces the following query:
{
"query": {
"bool": {
"should": [
{
"prefix": {
"name": "foobar"
}
},
{
"query_string": {
"query": "foobar"
}
},
{
"match": {
"name": {
"query": "foobar"
}
}
}
],
"minimum_number_should_match": 1
},
"filtered": {
"filter": {
"and": [
{
"term": {
"searchable": true
}
},
{
"range": {
"open_date": {
"lt": "2013-07-16"
}
}
}
]
}
}
},
"sort": [
{
"open_date": "desc"
}
]
}
However, the results that come back are not being sorted by "open_date". If I remove the filter:
{
"query": {
"bool": {
"should": [
{
"prefix": {
"name": "foobar"
}
},
{
"query_string": {
"query": "foobar"
}
},
{
"match": {
"name": {
"query": "foobar"
}
}
}
],
"minimum_number_should_match": 1
}
},
"sort": [
{
"open_date": "desc"
}
]
}
... the results come back as expected.
Any ideas?
I'm not sure about the Tire code, but the JSON does not correctly construct a filtered query. My guess is that this overflows and causes the sort element to also not be correctly parsed.
A filtered query should be constructed like this (see http://www.elasticsearch.org/guide/reference/query-dsl/filtered-query/ ):
{
"query": {
"filtered": { // Note: this contains both query and filter
"query": {
"bool": {
"should": [
{
"prefix": {
"name": "foobar"
}
},
{
"query_string": {
"query": "foobar"
}
},
{
"match": {
"name": {
"query": "foobar"
}
}
}
],
"minimum_number_should_match": 1
}
},
"filter": {
"and": [
{
"term": {
"searchable": true
}
},
{
"range": {
"open_date": {
"lt": "2013-07-16"
}
}
}
]
}
}
},
"sort": [
{
"open_date": "desc"
}
]
}
Cheers,
Boaz

Resources