Elasticsearch-net: 7.0.0-alpha2 -Trouble programmatically creating aggregations

Created on 17 May 2019  路  3Comments  路  Source: elastic/elasticsearch-net

NEST/Elasticsearch.Net version: 7.0.0-alpha2

Elasticsearch version: 7.0.1

Description of the problem including expected versus actual behavior:

I'm having trouble programmatically creating aggregations. I'm manually creating an AggregationContainer and then returning that from the Aggregations builder method. I'm not sure if there is a better way to do it or not. Please make sure that the meta values are being serialized because I have other scenarios where the meta does not get serialized and pass through to the server.

The following test code:

[Fact]
public void CanSendMetaWithAgg() {
    var client = GetClient();
    var index = CreateRandomIndex<MyType>(client);
    client.IndexMany(new[] {
        new MyType { Field4 = 1 },
        new MyType { Field4 = 8 },
        new MyType { Field4 = 3 }
    }, index);
    client.Refresh(index);

    var expectedResult = client.Search<MyType>(s => s.Aggregations(a => a.Max("max_field4", m => m.Field(f => f.Field4).Meta(me => me.Add("@field_type", "int")))));
    string expectedRequest = expectedResult.GetRequest();
    _logger.LogInformation("Expected: {Request}", expectedRequest);

    AggregationContainer container = new MaxAggregation("max_field4", "field4") { Meta = new Dictionary<string, object> {{"@field_type", "int"}} };
    var actualResult = client.Search<MyType>(s => s.Aggregations(container));
    string actualRequest = actualResult.GetRequest();
    _logger.LogInformation("Actual: {Request}", actualRequest);

    Assert.Contains("@field_type", actualRequest);
    Assert.Equal(expectedRequest, actualRequest);
}

Generates this output:

Assert.Contains() Failure
Not found: @field_type
In value:  200 POST http://localhost:9200/test_10a7c35839214fa99c483999c9a4db73/_search?pretty=true&typed_keys=true
{}

   at Foundatio.Parsers.Tests.QueryParserTests.CanSendMetaWithAgg() in /Users/ejsmith/Foundatio.Parsers/tests/Foundatio.Parsers.LuceneQueries.Tests/QueryParserTests.cs:line 859



07:27.29266 I:QueryParserTests - Expected: 200 POST http://localhost:9200/test_10a7c35839214fa99c483999c9a4db73/_search?pretty=true&typed_keys=true
{"aggs":{"max_field4":{"max":{"field":"field4"},"meta":{"@field_type":"int"}}}}

07:27.30304 I:QueryParserTests - Actual: 200 POST http://localhost:9200/test_10a7c35839214fa99c483999c9a4db73/_search?pretty=true&typed_keys=true
{}
Awaiting Response v7.0.0-beta1

Most helpful comment

Yeah, I seem to have it working. Thank you.

All 3 comments

@ejsmith the following line

```c#
var actualResult = client.Search(s => s.Aggregations(container));

doesn't compile, because `AggregationContainer` is not convertible to `AggregationDictionary`.

If you want to build up a collection of aggregations using the initializer syntax, it would be the following, [using `AggregationDictionary`](https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/writing-aggregations.html#_object_initializer_syntax_example_2)

```c#
var client = new ElasticClient();
var aggs = new AggregationDictionary
{
    { "max_field4", new MaxAggregation("max_field4", "field4") { Meta = new Dictionary<string, object> { { "@field_type", "int" } } } }
};

var actualResult = client.Search<object>(s => s.Aggregations(aggs));

The API is not so nice for this though because the aggregation key is repeated in the AggregationDictionary and in the aggregation itself.

It can be more succinctly expressed as

```c#
AggregationBase aggs = new MaxAggregation("max_field4", "field4") { Meta = new Dictionary { { "@field_type", "int" } } };

var actualResult = client.Search(s => s.Aggregations(aggs));

where [aggregations can be and'ed on](https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/writing-aggregations.html#_terse_object_initializer_syntax)

```c#
AggregationBase aggs = new MaxAggregation("max_field4", "field4") { Meta = new Dictionary<string, object> { { "@field_type", "int" } } };

aggs &= new MaxAggregation("max_field5", "field5");

var actualResult = client.Search<object>(s => s.Aggregations(aggs));

The API _does_ accept (which it _really shouldn't_ - and should not be used)

```c#
AggregationContainer aggs = new MaxAggregation("max_field4", "field4") { Meta = new Dictionary { { "@field_type", "int" } } };

var actualResult = client.Search(s => s.Aggregations(c => aggs));
`` This results in an empty{}` for aggregations due to how aggregations are collected internally and then serialized. We would need to investigate further to see how this API can be improved to prevent this kind of call from being possible

@ejsmith - hopefully the answer that @russcam has given above is helpful and gives clear guidance on how to use these methods.

Yeah, I seem to have it working. Thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gmarz picture gmarz  路  5Comments

Mpdreamz picture Mpdreamz  路  5Comments

hatem1975 picture hatem1975  路  3Comments

mszczepaniakebsco picture mszczepaniakebsco  路  5Comments

Mpdreamz picture Mpdreamz  路  3Comments