Mixed filters, using OR as well as AND, in ElasticSearch - elasticsearch

In your opinion what would be the best way to do the following?
I want to filter an ElasticSearch query by several ranges that are grouped in an OR filter, and then by one final range that needs to be included as an AND filter. The explanation is a bit crappy but hopefully the pseudo-code below will help...
Basically I tried structuring the following query:
{
"query":{
"multi_match":{
"query":"blue",
"fields":[
"name"
]
}
},
"sort":{
"_score":{
"order":"desc",
"missing":"_last"
}
},
"from":"0",
"size":"24",
"facets":{
"rating":{
"range":{
"field":"rating",
"ranges":[
{
"from":1
},
{
"from":2
},
{
"from":3
},
{
"from":4
}
]
}
},
"price":{
"range":{
"field":"price",
"ranges":[
{
"to":10
},
{
"from":10,
"to":100
},
{
"from":100,
"to":1000
}
{
"from":1000
}
]
}
}
},
"filter":{
"or":[
{
"range":{
"price":{
"from":"10",
"to":"100"
}
}
},
{
"range":{
"price":{
"from":"100",
"to":"1000"
}
}
}
],
"and":{
"numeric_range":{
"rating":{
"gte":"4"
}
}
}
}
}
This failed with the error that there was "No parser for element [numeric_range]". So I tried replacing:
"and":{
"numeric_range":{
"rating":{
"gte":"4"
}
}
}
with:
"numeric_range":{
"rating":{
"gte":"4"
}
}
The query now returns results but it's returning results with prices in the ranges 10-100, 100-1000 and ANY results with a rating greater than 4 (even if their price is outside of the defined range).
Any clues on how I could do this query? Do I need to be using a bool filter?

Ah ha, figured it out, with the help of Boaz Leskes over on the ElasticSearch mailing list!
It should be structured like this:
filter: {
bool: {
must: [
{
"numeric_range":{
"rating":{
"gte":"4"
}
}
}
],
should: [
{
"range":{
"price":{
"from":"10",
"to":"100"
}
}
},
{
"range":{
"price":{
"from":"100",
"to":"1000"
}
}
}
]
}
}

Related

Why search performance is difference between from&size and search&after

There are hundreds of millions of documents in my index. When I search, I find that search&after is much slower than from&size。 Use from&size,search is quick,took several ms return,but use search after,it took 20 seconds。My search result is sort by time and key(a keyword copy of _id) ,Why?what's the difference?
search cmd:
{
"query":{
"bool":{
"filter":[
{
"query_string":{
"query":"*"
}
},
{
"range":{
"__time__":{
"gte":1324958207,
"lte":1724958207
}
}
}
]
}
},
"size":10,
"sort":[
{
"__time__":{
"order":"desc"
}
},
{
"__key__":{
"order":"desc"
}
}
],
"search_after":[
1630594662000,
"6130e666-2-67e9e3-f5-1"
],
"profile":true
}
profile:
{"searches":[
{
"query":[
{
"type":"BoostQuery",
"description":"(ConstantScore(DocValuesFieldExistsQuery [field=__time__]))^0.0",
"time_in_nanos":45722536283,
"breakdown":{
"set_min_competitive_score_count":0,
"match_count":0,
"shallow_advance_count":0,
"set_min_competitive_score":0,
"next_doc":45722241414,
"match":0,
"next_doc_count":410919487,
"score_count":0,
"compute_max_score_count":0,
"compute_max_score":0,
"advance":19517,
"advance_count":39,
"score":0,
"build_scorer_count":78,
"create_weight":14271,
"shallow_advance":0,
"create_weight_count":1,
"build_scorer":261081
},
"children":[
{
"type":"DocValuesFieldExistsQuery",
"description":"DocValuesFieldExistsQuery [field=__time__]",
"time_in_nanos":16571715415,
"breakdown":{
"set_min_competitive_score_count":0,
"match_count":0,
"shallow_advance_count":0,
"set_min_competitive_score":0,
"next_doc":16571493898,
"match":0,
"next_doc_count":410919487,
"score_count":0,
"compute_max_score_count":0,
"compute_max_score":0,
"advance":15074,
"advance_count":39,
"score":0,
"build_scorer_count":78,
"create_weight":517,
"shallow_advance":0,
"create_weight_count":1,
"build_scorer":205926
}
}
]
}
],
"rewrite_time":116538,
"collector":[
{
"name":"PagingFieldCollector",
"reason":"search_top_hits",
"time_in_nanos":30851166561
}
]
}
],
"aggregations":[
]
}
Because search_after use scroll approach for filtering which supposed to sort all the data before filtering, instead of from/size which only retrieved elements as a stream, and will be slower and hit memory as much as you go deeper with a from

Percentage for each bucket

Im trying to get the percentage for each bucket in elasticsearch 7.1 with this query:
{
"size":0,
"aggs":{
"group_by_status":{
"terms":{
"field":"status.keyword"
},
"aggs":{
"percentage":{
"sum":{
"script":"100/total"
}
}
}
},
"total":{
"sum_bucket":{
"buckets_path":"group_by_status>_count"
}
}
}
}
This one doesnt work because you cant use the total count of status and I get error that the variable total is not define but I want to know if theres a way to get this result with the percentage of each bucket:
{
"aggregations":{
"group_by_status":{
"doc_count_error_upper_bound":0,
"sum_other_doc_count":0,
"buckets":[
{
"key":"Abierto",
"doc_count":2,
"percentage":{
"value":40.0
}
},
{
"key":"Cerrado",
"doc_count":2,
"percentage":{
"value":40.0
}
},
{
"key":"Pausado",
"doc_count":1,
"percentage":{
"value":20.0
}
}
]
},
"total":{
"value":5.0
}
}
}

Hello, I am trying to use wildcard query with filters in elastric search in my node js application

I am getting search item from user as
let eventSearch="*"+event.SearchTerm+"*";
This is the query object
let queryObject =
{
index: 'mark_deling_test2',
type: 'product',
body: {
"from" : event.StartIndex, "size" : event.ResultSize,
"query": {
"filtered":{
"query":{
"query_string":{
"fields": [ "Name^2.5", "Description", "keywords^1.75" ],
"query":eventSearch,
"analyze_wildcard":true
}
},
"filter":{
"term":{
"groups": "CA-IBO"
}
}
}
}
}
};
Then sending this query object for searching
This is not working. If I don't use the filter it works.
Please Help!
Get mark_deling_test2/_search
{
“query”: {
“bool”: {
“must”: {
“query_string”: {
“query”: “nut*“,
“fields”: [“Name”, “Description”, “keywords”]
}
},
“filter”: {
“term”: {
“groups”: “US-IBO”
}
}
}
}
}

Has Child join field issue

Good day:
I've setup a Parent/Child relationship model between Facility and FacilityType. Currently I'm trying to query the Facility and at the same time trying to load the children by using the HasChild query but, I'm getting the following error:
{
"aggs":{
"Capacity":{
"children":{
"type":"facilitytype"
},
"aggs":{
"Capacity":{
"histogram":{
"field":"capacity",
"interval":10.0,
"missing":0.0
}
}
}
},
"Distance":{
"histogram":{
"field":"businessLocation",
"interval":10.0,
"order":{
"_count":"desc"
}
}
}
},
"query":{
"bool":{
"should":[
{
"bool":{
"must":[
{
"geo_distance":{
"boost":1.1,
"distance":"200.0m",
"distance_type":"arc",
"businessLocation":{
"lat":38.958878299999988,
"lon":-77.365260499999991
}
}
},
{
"has_child":{
"_name":"FacilityType",
"type":"doc",
"query":{
"match_all":{
}
}
}
}
]
}
},
{
"geo_distance":{
"boost":1.1,
"distance":"200.0m",
"distance_type":"arc",
"serviceAreas":{
"lat":38.958878299999988,
"lon":-77.365260499999991
}
}
}
]
}
}
}
I'm getting this error when I execute the query:
[has_child] join field [joinField] doesn't hold [doc] as a child

Elasticsearch multi date range aggregation using java api

I use elasticsearch 2.2 and I want to do some aggregations like this:
{
"bool":{
"must":[
{
"query_string":{
"default_field":"berid",
"query":"F600-HHP1"
}
},
{
"query_string":{
"default_field":"matnr",
"query":"91P9289AAZZ"
}
}
]
},
"size":0,
"aggs":{
"count_by_date_range":{
"date_range":{
"field":"zzupload",
"ranges":[
{
"from":"2016-03-01",
"to":"2016-03-06"
},
{
"from":"2016-03-07",
"to":"2016-03-13"
},
{
"from":"2016-03-14",
"to":"2016-03-20"
},
{
"from":"2016-03-21",
"to":"2016-03-27"
},
{
"from":"2016-03-28",
"to":"2016-04-03"
},
{
"from":"2016-04-04",
"to":"2016-04-10"
},
{
"from":"2016-04-11",
"to":"2016-04-17"
},
{
"from":"2016-04-18",
"to":"2016-04-24"
},
{
"from":"2016-04-25",
"to":"2016-05-01"
},
{
"from":"2016-05-02",
"to":"2016-05-08"
},
{
"from":"2016-05-09",
"to":"2016-05-15"
},
{
"from":"2016-05-16",
"to":"2016-05-22"
},
{
"from":"2016-05-23",
"to":"2016-05-29"
},
{
"from":"2016-05-30",
"to":"2016-06-05"
},
{
"from":"2016-06-06",
"to":"2016-06-12"
},
{
"from":"2016-06-13",
"to":"2016-06-19"
}
]
},
"aggs":{
"total_fcst_qty":{
"sum":{
"field":"zzamqtu"
}
}
}
}
}
}
I need to calculate the sum of quantity on date range("from":"2016-03-01", "to":"2016-03-06", ...).But it's look like elasticsearch java api didn't support multi date_range.Here is my code:
SearchRequestBuilder searchBuilder = esClient.prepareSearch(Elasticsearch_sap_material_fcst_Index)
.setTypes(Elasticsearch_material_fcst_Type)
.setQuery(sb.toString())
.addAggregation(AggregationBuilders.dateRange("count_by_date_range").field("zzupload")
.addRange("2016-03-01", "2016-03-06")
.subAggregation(AggregationBuilders.sum("total_fcst_qty")));
How to calculate multiple date range using java api?
Thanks
You can just add multiple ranges like you did with the REST API:
SearchRequestBuilder searchBuilder = esClient.prepareSearch(Elasticsearch_sap_material_fcst_Index)
.setTypes(Elasticsearch_material_fcst_Type)
.setQuery(sb.toString())
.addAggregation(AggregationBuilders.dateRange("count_by_date_range").field("zzupload")
.addRange("2016-03-01", "2016-03-06")
.addRange("2016-05-23", "2016-05-29")
.subAggregation(AggregationBuilders.sum("total_fcst_qty")));
If you have a look at the source code, you can see that each call to addRange appends the new range to a list of ranges.

Resources