how to use two parallel Aggregation for elasticsearch nest - elasticsearch

Like bellow http request:
base on TERM "service_project" aggr, there are 2 another SUM aggr "service_hour_price" and "servic_part_price". Can I use Elasticsearch Nest do the same thing?
"aggs": {
"3": {
"terms": {
"field": "service_project",
"size": 50,
"order": {
"1": "desc"
}
},
"aggs": {
"1": {
"sum": {
"field": "service_hour_price"
}
},
"2": {
"sum": {
"field": "servic_part_price"
}
}
}
}
}
Now I can use only one SUM Aggr base on That Term Aggr, like this:
return s.Aggregations(a => a
.Terms("names", st => st
.Field(o => o.service_project)
.OrderDescending("sum")
.Size(term_count)
.Aggregations(aa => aa
.Sum("sum", m => m
.Field(o => o.service_hour_price)))));

You are almost there:
s.Aggregations(a => a
.Terms("3", t => t
.Field("service_project")
.Size(50)
.OrderDescending("1")
.Aggregations(aa => aa
.Sum("1", sum => sum.Field("service_hour_price"))
.Sum("2", sum => sum.Field("service_part_price")))
));
Hope it helps.

Related

Convert elastic search query + aggregations to nest syntax

I need to turn the following nested query and aggregations as written in Kibana to c# nest syntax.
The main issue is regarding the "harvest-date" sub-aggregation (I need to set it to the last 3 months). but also not sure the query itself is the best practice.
GET tdnetindex/_search
{
"size": 0,
"aggs": {
"TermsAggregation": {
"terms": {
"field": "database",
"size": 100
},
"aggs": {
"DateHistogramAggregation": {
"date_histogram": {
"field": "harvest_date",
"interval": "month"
}
}
}
}
},
"query": {
"bool": {
"filter": {
"range": {
"harvest_date": {
"gte": "now-3M/M"
}
}
}
}
}
}
what I did so far was:
var query = elasticClient.Search<ElasticResponse>(s => s
.Size(0)
.Aggregations(a1 => a1
.Terms("TermsAggregation", t => t
.Field(f => f.DataBase)
.Size(100)
.Aggregations(a2 => a2
.DateHistogram("DateHistogramAggregation", dh => dh
.Field(f => f.HarvestDate)
.Interval(DateInterval.Month)
)
)
)
)
.Query(q => q
.Bool(b => b
.Filter(f => f
.Range(r => r
.GreaterThanOrEquals(....);
)
)
)
)
)
You're almost there, just need to use .DateRange(r => r...) instead of .Range(r => r...).
For the DateMath expression, you can use the string "now-3M/M" directly, or translate to
DateMath.Now.Subtract("3M").RoundTo(DateMathTimeUnit.Month)

Elasticsearch - How to get the sum of fields with terms?

I'm trying to get a sum of some fields, with terms (let's say, number of files of specific user with Id).
First I tried:
_mainManager.Client.Search<object>
(q => q
.Type("Mail")
.Filter(c => c.Term("SentMail_Sender_Id", userId))
.Aggregations(a => a.Terms("sum", g => g.Field("SentMail_Upload_Files_Count")))
.Size(1));
But no luck in Agg property, so I tried this:
_mainManager.Client.Search<object>
(q => q
.Type("Mail")
.Aggregations(a => a.Filter("fil", b => b.Filter(c => c.Term("SentMail_Sender_Id", userId))).Sum("sum", f => f.Field("SentMail_Upload_Files_Count"))));
But then again, no luck there.
Can anyone help?
The following code gives you the result that you need I thing:
PUT /mail/message/1
{
"SentMail_Sender_Id":1,
"SentMail_Upload_Files_Count":10
}
PUT /mail/message/2
{
"SentMail_Sender_Id":1,
"SentMail_Upload_Files_Count":2
}
PUT /mail/message/3
{
"SentMail_Sender_Id":2,
"SentMail_Upload_Files_Count":7
}
GET /mail/_search?search_type=count
{
"query": {
"filtered": {
"filter": {
"term": {
"SentMail_Sender_Id": 1
}
}
}
},
"aggs": {
"total": {
"stats": {
"field": "SentMail_Upload_Files_Count"
}
}
}
}
The response is:
"aggregations": {
"total": {
"count": 2,
"min": 2,
"max": 10,
"avg": 6,
"sum": 12
}
}

Elasticsearch - Term null?

I'm having trouble matching null terms in NEST.
I'm trying to get some details via a query.
It works ok, but one thing I can't understand -
For some reason I can't do a term that equals to null value.
What am I doing wrong?
My Code:
result = _mainManager.Client.Search<object>
(q => q
.Type("Mail")
.Query(c =>
c.Term("SentMail_Sender_Id", userId) &&
c.Term("SentMail_EmbedAccountId", null) &&
!c.Term("SentMail_Status", Status.REMOVED.ToString().ToLower()) &&
c.Range(v => v.OnField("SentMail_Upload_Files_Count").Greater(0)))
.Size(int.MaxValue)
.Sort(s => s.OnField("SentMail_Creation_Date").Descending()));
It works ok, no null term is found in my result Json:
{
"size": 2147483647,
"sort": [
{
"SentMail_Creation_Date": {
"order": "desc"
}
}
],
"query": {
"bool": {
"must": [
{
"term": {
"SentMail_Sender_Id": {
"value": 7186
}
}
},
{
"range": {
"SentMail_Upload_Files_Count": {
"gt": "0"
}
}
}
],
"must_not": [
{
"term": {
"SentMail_Status": {
"value": "removed"
}
}
}
]
}
}
}
Found it!
result = _mainManager.Client.Search<object>
(q => q
.Type("Mail")
.Query(c =>
c.Term("SentMail_Sender_Id", userId) &&
!c.Term("SentMail_Status", Status.REMOVED.ToString().ToLower()) &&
c.Range(v => v.OnField("SentMail_Upload_Files_Count").Greater(0)))
.Filter(f => f.Missing("SentMail_EmbedAccountId"))
.Size(int.MaxValue)
.Sort(s => s.OnField("SentMail_Creation_Date").Descending()));

Elastic Search - Creating Query with NEST

Given the query:
GET places/_search
{
"query": {
"match_all": {}
},
"size": 0,
"aggs": {
"filtered_cells": {
"filter": {
"geo_bounding_box": {
"loc": {
"top_left": {
"lat": 53.480950,
"lon": -2.2374300
},
"bottom_right": {
"lat": 51.5085300,
"lon": -0.1257400
}
}
}
},
"aggs": {
"cells": {
"geohash_grid": {
"field": "loc",
"precision": "precision"
},
"aggs": {
"center_lat": {
"avg": {
"script": "doc['loc'].lat"
}
},
"center_lon": {
"avg": {
"script": "doc['loc'].lon"
}
}
}
}
}
}
}
}
I am trying to move this query into a piece of code I am developing, but I am having trouble structuring the query above using the NEST library.
Here is what I have so far:
var s = new SearchDescriptor<FacebookGraphResponse>()
.MatchAll()
.From(0)
.Size(10)
.Filter(filter => filter
.GeoBoundingBox(f => f.Loc, 53.480950, -2.2374300, 51.5085300, -0.1257400)
);
Is anyone able to provide any input on how I can translate this query to nest, as I am currently stumped.
Many Thanks
Solved it!
var s = new SearchDescriptor<FacebookGraphResponse>()
.MatchAll()
.Size(0)
.Aggregations(aggs => aggs
.Filter("filtered_cells", f => f
.Filter(f1 => f1
.GeoBoundingBox(bb => bb.Loc, -2.2374300, 53.480950, -0.1257400, 51.5085300))
.Aggregations(a => a
.GeoHash("cells", geo => geo
.GeoHashPrecision(GeoHashPrecision.Precision10)
.Field("loc")
.Aggregations(a1 => a1
.Average("center_lat", x => x.Script("doc['loc'].lat"))
.Average("center_lon", x => x.Script("doc['loc'].lon")))))));

ElasticSearch .NET Nest Sub Aggregation

Consider the following aggregation and sub aggregation:
.Aggregations(a => a
.Terms("ByCustomerByImpressionCount", tad => tad
.Field(o => o.CustomerName)
.OrderDescending("sumImpressionCount")
.Aggregations(ad => ad
.Sum("sumImpressionCount", sad => sad
.Field(o => o.ImpressionCount)
)
)
))
The query works fine, and I get results.
I can access the top aggregation with:
var agg = results.Aggs.Terms("ByCustomerByImpressionCount");
According to the docs, I should be able to get the sub agg with:
var subAgg = agg.Aggs.Sum("sumImpressionCount");
But Aggs isn't even a property of agg - any ideas?
EDIT:
This is the only way I've been able to get to the sub aggregation:
PopulateList(results.Aggs.Terms("CustomersByImpressionCount").Items, CustomersByImpressionCount);
private void PopulateList(IList<KeyItem> items, List<DataContainer> listToPopulate)
{
items.ForEach(item =>
{
listToPopulate
.Add(new DataContainer() { Name = item.Key, Sum = ((ValueMetric)item.Aggregations.First().Value).Value });
});
}
...but this seems to be overly complicated. Here is the ES query:
"query": {
"bool": {
"must": [
{ "range": { "requestedShipDate": {
"gte": "2014-11-26",
"lte": "2015-02-03"
} }
}
],
"must_not": [
{"terms": {
"status": [
"Order Shipped",
"Canceled",
"Completed"
]
}}
]
}
},
"aggs": {
"ByCustomerByImpressionCount": {
"terms": {
"field": "customerName",
"order": { "sumImpressionCount": "desc" }
},
"aggs": {
"sumImpressionCount": { "sum": { "field": "impressionCount" }}
}
}}
And here is partial response:
"ByCustomerByImpressionCount": {
"doc_count_error_upper_bound": -1,
"sum_other_doc_count": 26785,
"buckets": [
{
"key": "<One of our customers>",
"doc_count": 1722,
"sumImpressionCount": {
"value": 9583176
}
}
The documentation is wrong. We'll fix that ASAP.
Here is the correct way to access your aggregations:
var terms = results.Aggs.Terms("ByCustomerByImpressionCount");
foreach(var term in terms.Items)
{
var sum = term.Sum("sumImpressionCount");
}

Resources