Aggregation on geo_piont elasticsearch - elasticsearch

Is there a way to aggregate on a geo_point field and to receive the actual lat long?
all i managed to do is get the hash geo.
what i did so far:
creating the index
PUT geo_test
{
"mappings": {
"sharon_test": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
}
adding X docs with different lat long
POST geo_test/sharon_test
{
"location": {
"lat": 45,
"lon": -7
}
}
ran this agg:
GET geo_test/sharon_test/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
]
}
},
"aggs": {
"locationsAgg": {
"geohash_grid": {
"field": "location",
"precision" : 12
}
}
}
}
i got this result:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "geo_test",
"_type": "sharon_test",
"_id": "fGb4uGEBfEDTRjcEmr6i",
"_score": 1,
"_source": {
"location": {
"lat": 41.12,
"lon": -71.34
}
}
},
{
"_index": "geo_test",
"_type": "sharon_test",
"_id": "oWb4uGEBfEDTRjcE7b6R",
"_score": 1,
"_source": {
"location": {
"lat": 4,
"lon": -7
}
}
}
]
},
"aggregations": {
"locationsAgg": {
"buckets": [
{
"key": "ebenb8nv8nj9",
"doc_count": 1
},
{
"key": "drm3btev3e86",
"doc_count": 1
}
]
}
}
}
I want to know if i can get one of the 2:
1. convert the "key" that is currently representing as a geopoint hash to the sources lat/long
2. show the lat, long in the aggregation in the first place
Thanks!
P.S
I also tried the other geo aggregations but all they give me is the number of docs that fit my aggs conditions, i need the actual values
E.G
wanted this aggregation to return all the locations i had in my index, but it only returned the count
GET geo_test/sharon_test/_search
{
"query": {
"bool": {
"must": [
{
"match_all": {}
}
]
}
},
"aggs": {
"distanceRanges": {
"geo_distance": {
"field": "location",
"origin": "50.0338, 36.2242 ",
"unit": "meters",
"ranges": [
{
"key": "All Locations",
"from": 1
}
]
}
}
}
}

You can actually use geo_bounds inside the geo_hash to get a bounding box to narrow it down precisely but to get the exact location you will need to decode the geohash
GET geo_test/sharon_test/_search
{
"query":{
"bool":{
"must":[
{
"match_all":{
}
}
]
}
},
"aggs":{
"locationsAgg":{
"geohash_grid":{
"field":"location",
"precision":12
},
"aggs":{
"cell":{
"geo_bounds":{
"field":"location"
}
}
}
}
}
}

Related

How to get values count in different ranges from array in elasticsearch which is separate for each document?

I want to get count of values for different ranges from an array for each document. For example, a document of student contains array "grades" which has different score per subject e.g. Maths - score 71, Science - score 91, etc. So, I want to get ranges per student like Grade A - 2 subject, Grade B - 1 subject.
So, the mapping is something like this:
{
"student-grades": {
"mappings": {
"properties": {
"grades": {
"type": "nested",
"properties": {
"subject": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"score": {
"type": "float"
}
}
},...
}
}
}
}
For counting ranges I have created a query something like this:
GET student-grades/_search
{
"aggs": {
"nestedAgg": {
"nested": {
"path": "grades"
},
"aggs": {
"gradeRanges": {
"range": {
"field": "grades.score",
"ranges": [
{
"key": "range1",
"to": 35.01
},
{
"key": "range2",
"from": 35.01,
"to": 50.01
},
{
"key": "range3",
"from": 50.01,
"to": 60.01
},
{
"key": "range4",
"from": 60.01,
"to": 70.01
},
{
"key": "range5",
"from": 70.01
}
]
},
"aggs": {
"perDoc": {
"top_hits": {
"size": 10
}
}
}
}
}
}
}
}
But, it is giving a single list of ranges for all documents combined. The number of subjects is not fixed, so I can't set a random size in top_hits. So, how can I get all ranges per document? (I am new to elasticsearch, so I am not aware about its all features.)
I used a painless script to solve this problem. Here is the query:
GET grades/_search
{
"script_fields": {
"gradeRanges": {
"script": {
"source": """
List gradeList = doc['grades.score'];
List gradeRanges= new ArrayList();
for(int i=0; i<5; i++) {
gradeRanges.add(0);
}
for(int i=0; i<gradeList.length; i++) {
if(gradeList[i]<=35.0) {
gradeRanges[0]++;
} else if(gradeList[i]<=50.0) {
gradeRanges[1]++;
} else if(gradeList[i]<=60.0) {
gradeRanges[2]++;
} else if(gradeList[i]<=70.0) {
gradeRanges[3]++;
} else {
gradeRanges[4]++;
}
}
return gradeRanges;
"""
}
}
},
"size": 100
}
This will give me separate grade ranges for each document, like this:
{
"took": 38,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 12,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "grades",
"_id": "11",
"_score": 1,
"fields": {
"gradeRanges": [
0,
2,
0,
3,
1
]
}
},
{
"_index": "grades",
"_id": "12",
"_score": 1,
"fields": {
"gradeRanges": [
0,
1,
0,
1,
1
]
}
}
]
}
}

Is it possible to use a query result into another query in ElasticSearch?

I have two queries that I want to combine, the first one returns a document with some fields.
Now I want to use one of these fields into the new query without creating two separates ones.
Is there a way to combine them in order to accomplish my task?
This is the first query
{
"_source": {
"includes": [
"data.session"
]
},
"query": {
"bool": {
"must": [
{
"match": {
"field1": "9419"
}
},
{
"match": {
"field2": "5387"
}
}
],
"filter": [
{
"range": {
"timestamp": {
"time_zone": "+00:00",
"gte": "2020-10-24 10:16",
"lte": "2020-10-24 11:16"
}
}
}
]
}
},
"size" : 1
}
And this is the response returned:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 109,
"relation": "eq"
},
"max_score": 3.4183793,
"hits": [
{
"_index": "file",
"_type": "_doc",
"_id": "UBYCkgsEzLKoXh",
"_score": 3.4183793,
"_source": {
"data": {
"session": "123456789"
}
}
}
]
}
}
I want to use that "data.session" into another query, instead of rewriting the value of the field by passing the result of the first query.
{
"_source": {
"includes": [
"data.session"
]
},
"query": {
"bool": {
"must": [
{
"match": {
"data.session": "123456789"
}
}
]
}
},
"sort": [
{
"timestamp": {
"order": "asc"
}
}
]
}
If you mean to use the result of the first query as an input to the second query, then it's not possible in Elasticsearch. But if you share your query and use-case, we might suggest you better way.
ElasticSearch does not allow sub queries or inner queries.

Elasticsearch- how to do query with condition and sort out the required fied without duplicate

i was new to ES, i am now able to sort a field in my DB with condition
alarm!=0
the code was here:
{
"size":1,
"query": {
"bool": {
"must_not": {
"term": {
"header.alarmStatus": 0
}
}
}//bool
//query
}
}
and it shows that it have around 4000 hit which is all i want
the response for that (size = 1) was as follow
"hits": {
"total": {
"value": 3842,
"relation": "eq"
},
"max_score": 0.0,
"hits": [
{
"_index": "index123",
"_type": "meter",
"_id": "63iti3QBSliyJ__JFt6C",
"_score": 0.0,
"_source": {
"header": {
"meterId": 1245,
},
"data": {
"seqNum": 72
}
}
]
}
And my question is how can i do the query with condition "header.alarmStatus": !=0
and list all the meter ID with duplicate counts ?
thanks
Jeff
As far as I can understand, you need to list all the meterId (removing the duplicate count) for the query with the condition "header.alarmStatus": !=0. For this, you can use the terms aggregation with cardinality aggregation as sub aggregation
Index Data:
{
"header": {
"meterId": 1246,
"alarmStatus": 3
},
"data": {
"seqNum": 72
}
}
{
"header": {
"meterId": 1246,
"alarmStatus": 2
},
"data": {
"seqNum": 72
}
}
{
"header": {
"meterId": 1245,
"alarmStatus": 1
},
"data": {
"seqNum": 72
}
}
Search Query:
{
"query": {
"bool": {
"must_not": {
"term": {
"header.alarmStatus": 0
}
}
}
},
"aggs": {
"genres": {
"terms": {
"field": "header.meterId"
},
"aggs": {
"item_count": {
"cardinality": {
"field": "header.meterId"
}
}
}
}
}
}
Search Result:
"aggregations": {
"genres": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1246,
"doc_count": 2,
"item_count": {
"value": 1
}
},
{
"key": 1245,
"doc_count": 1,
"item_count": {
"value": 1
}
}
]
}

ElasticSearch - search for any nested field that is in range

I have the next filed as part of an elastic element:
"PayPlan" : {
"ActivePlans" : {
"plan1" : {
"startsOn" : "1",
"endsOn" : "999999"
}
},
"someOtherData" : [
NumberLong(0), 0]
},
plan names are completely without logic (can be 'plan2323a' or 'plan_hh_jj' and so on).
How can I search for ALL the elements that have ANY plan that the startsOn is smaller then X and endsOn is bigger than X?
Thank you all
I am unable to do this with query_string or by using range on query and using the next format "PayPlan.ActivePlans.*.startsOn" (the asterisk did not work as a wildcard in range
Thank you all
This is the elasticsearch query I have working now but I want to change 'plan1' into '*' so it will search for any sub plan:
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{
"match_all": {}
},
{
"or": {
"filters": [
{
"bool": {
"must": [
{
"range": {
"PayPlan.ActivePlans.plan1.startsOn": {
"lte": "1234"
}
}
},
{
"range": {
"PayPlan.ActivePlans.plan1.endsOn": {
"gte": "1236"
}
}
}
]
}
}
]
}
}
]
}
}
}
}
}
You could start with a query string like:
GET test1/_search
{
"query": {
"query_string": {
"default_field": "PayPlan.ActivePlans.plan*.startsOn",
"query": ">0"
}
}
}
The output (with a quick test run):
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test1",
"_type": "plan",
"_id": "AVq000G1mKJs7uLU8liY",
"_score": 1,
"_source": {
"PayPlan": {
"ActivePlans": {
"plan2": {
"startsOn": "2",
"endsOn": "999998"
}
}
}
}
},
{
"_index": "test1",
"_type": "plan",
"_id": "AVq00p0pmKJs7uLU8liW",
"_score": 1,
"_source": {
"PayPlan": {
"ActivePlans": {
"plan1": {
"startsOn": "1",
"endsOn": "999999"
}
}
}
}
}
]
}
}

Term filter for boolean types does not return any results

I have some data with the following index (this is just the relevant piece):
{
"content": {
"mappings" : {
"content": {
"properties": {
"published" : {
"type": "boolean"
}
}
}
}
}
}
When I query for everything using
GET content/content/_search
{}
I get back plenty of documents with published: true, but when I query using a term filter:
GET content/content/_search
{
"filter": {
"term": {
"published": true
}
}
}
I don't get any results. What's wrong with my term filter?
Wierd, it works for me on ES1.0:
I indexed a doc like this:
PUT /twitter/tweet/1
{
"bool":true
}
Here is my mapping:
GET /twitter/tweet/_mapping
{
"twitter": {
"mappings": {
"tweet": {
"properties": {
"bool": {
"type": "boolean"
}
}
}
}
}
}
I can search like this:
GET twitter/tweet/_search
{
"filter": {
"term": {
"bool": true
}
}
}
I got these results:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "twitter",
"_type": "tweet",
"_id": "1",
"_score": 1,
"_source": {
"bool": true
}
}
]
}
}
The problem was unrelated to querying... seems like my custom river was importing data incorrectly.

Resources