# Is it possible to add aggregations piecemeal to the Nest .NET Library?

**URL:** <https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909>\
**Category:** Elasticsearch\
**Created:** [August 10, 2018, 4:57pm UTC](https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909 "2018-08-10T16:57:25Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rgelb](https://avatars.discourse-cdn.com/v4/letter/r/da6949/32.png) [@rgelb](https://discuss.elastic.co/u/rgelb)\
**Post date:** [August 10, 2018, 4:57pm UTC](https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909/1 "2018-08-10T16:57:25Z")

</div>

I have the following code which works:

```auto
var search = new SearchDescriptor<Foo>();

search.Aggregations(agg =>
  agg.Cardinality("dedup", cd => cd.Field(fi => fi.AddressHash).PrecisionThreshold(40000))
  .Filter("dontDedup", fl => fl.Filter(ft => ft.Term(te => te.AddressHash, "0")))
  .Min("min_lat", fl => fl.Field(fi => fi.Latitude))
  .Max("max_lat", fl => fl.Field(fi => fi.Latitude))
  .Min("min_lon", fl => fl.Field(fi => fi.Longitude))
  .Max("max_lon", fl => fl.Field(fi => fi.Longitude))
);

```

But what I want is to add the aggregations to the SearchDescriptor piecemeal.

```auto
search.Aggregations(agg =>
  agg.Cardinality("dedup", cd => cd.Field(fi => fi.AddressHash).PrecisionThreshold(40000))
  .Filter("dontDedup", fl => fl.Filter(ft => ft.Term(te => te.AddressHash, "0"))));

```

then, if a condition is met

```auto
if (someCondition) {
    search.Aggregations(agg => agg
        .Min("min_lat", fl => fl.Field(fi => fi.Latitude))
        .Max("max_lat", fl => fl.Field(fi => fi.Latitude))
        .Min("min_lon", fl => fl.Field(fi => fi.Longitude))
        .Max("max_lon", fl => fl.Field(fi => fi.Longitude))
    );
}

```

However, the 2nd search.Aggregations... wipes out the aggregations added in the 1st statement.  
Is it possible to add .Aggregations piecemeal? I didn't see a .Add method or anything like that.

---

<div class="post-metadata">

**Author:** ![forloop](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/forloop/32/9021_2.png) [@forloop](https://discuss.elastic.co/u/forloop)\
**Post date:** [August 13, 2018, 12:01am UTC](https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909/2 "2018-08-13T00:01:43Z")

</div>

There are a couple of approaches typically taken

1. `search.Aggregations(...)` takes a `Func<AggregationContainerDescriptor<T>, IAggregationContainer>`, or in words, a method that accepts an `AggregationContainerDescriptor<T>` and returns an `IAggregationContainer`.

or

1. Use the object initializer syntax to compose an `IAggregationContainer`, using an `IDictionary<string, IAggregate>` and `AggregationDictionary`, or using overloaded operators on `IAggregate` types to `&&` them together.

Take a look at the [Writing Aggregations documentation](https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/writing-aggregations.html) for some examples.

---

<div class="post-metadata">

**Author:** ![rgelb](https://avatars.discourse-cdn.com/v4/letter/r/da6949/32.png) [@rgelb](https://discuss.elastic.co/u/rgelb)\
**Post date:** [August 13, 2018, 6:37am UTC](https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909/3 "2018-08-13T06:37:08Z")

</div>

@forloop I am still not grokking how to actually accomplish this. In the link you provided, there are references to the Combine method, but it's not shown how to implement it.

Using my example, can you show how to accomplish this?

---

<div class="post-metadata">

**Author:** ![forloop](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/forloop/32/9021_2.png) [@forloop](https://discuss.elastic.co/u/forloop)\
**Post date:** [August 14, 2018, 10:35pm UTC](https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909/4 "2018-08-14T22:35:03Z")

</div>

> [@rgelb](#):
>
> Using my example, can you show how to accomplish this?

Here's an example. Starting with converting the lamdba expression to one with a statement body

```auto
var client = new ElasticClient();

var includeMinMax = true;

client.Search<MyDocument>(s => s
    .Aggregations(agg =>
    {
        agg.Cardinality("dedup", cd => cd
            .Field(fi => fi.AddressHash)
            .PrecisionThreshold(40000)
        )
        .Filter("dontDedup", fl => fl
            .Filter(ft => ft
                .Term(te => te.AddressHash, "0")
            )
        );

        if (includeMinMax)
        {
            agg.Min("min_lat", fl => fl.Field(fi => fi.Latitude))
               .Max("max_lat", fl => fl.Field(fi => fi.Latitude))
               .Min("min_lon", fl => fl.Field(fi => fi.Longitude))
               .Max("max_lon", fl => fl.Field(fi => fi.Longitude));
        }

        return agg;
    })
);

```

You can then extract the lambda statement body out to a method

```auto
client.Search<MyDocument>(s => s
    .Aggregations(agg => BuildAggregations(agg, includeMinMax))
);

private static IAggregationContainer BuildAggregations(AggregationContainerDescriptor<MyDocument> agg, bool includeMinMax)
{
    agg.Cardinality("dedup", cd => cd
        .Field(fi => fi.AddressHash)
        .PrecisionThreshold(40000)
    )
    .Filter("dontDedup", fl => fl
        .Filter(ft => ft
            .Term(te => te.AddressHash, "0")
        )
    );
    
    if (includeMinMax)
    {
        agg.Min("min_lat", fl => fl.Field(fi => fi.Latitude))
           .Max("max_lat", fl => fl.Field(fi => fi.Latitude))
           .Min("min_lon", fl => fl.Field(fi => fi.Longitude))
           .Max("max_lon", fl => fl.Field(fi => fi.Longitude));
    }

    return agg;
}

```

Or even the entire lambda

```auto
client.Search<MyDocument>(s => s
    .Aggregations(BuildAggregations(includeMinMax))
);

private static Func<AggregationContainerDescriptor<MyDocument>, IAggregationContainer> BuildAggregations(bool includeMinMax)
{
    return agg =>
    {
        agg.Cardinality("dedup", cd => cd
            .Field(fi => fi.AddressHash)
            .PrecisionThreshold(40000)
        )
        .Filter("dontDedup", fl => fl
            .Filter(ft => ft
                .Term(te => te.AddressHash, "0")
            )
        );

        if (includeMinMax)
        {
            agg.Min("min_lat", fl => fl.Field(fi => fi.Latitude))
               .Max("max_lat", fl => fl.Field(fi => fi.Latitude))
               .Min("min_lon", fl => fl.Field(fi => fi.Longitude))
               .Max("max_lon", fl => fl.Field(fi => fi.Longitude));
        }

        return agg;
    };
}

```

For the object initializer syntax

```auto
var client = new ElasticClient();
var includeMinMax = true;

var aggs = new Dictionary<string, AggregationContainer>{
    { "dedup", new CardinalityAggregation("dedup", Infer.Field<MyDocument>(f => f.AddressHash))
                {
                    PrecisionThreshold = 40000
                }
    },
    { "filter", new FilterAggregation("dontDedup")
                {
                    Filter = new TermQuery
                    {
                        Field = Infer.Field<MyDocument>(f => f.AddressHash),
                        Value = "0"
                    }
                }
    }
};

if (includeMinMax) 
{
    aggs.Add(...);
}

client.Search<MyDocument>(new SearchRequest<MyDocument>
{
   Aggregations = new AggregationDictionary(aggs)
});

```

Using a dictionary can be long winded, so aggregations can be combined with `&&`

```auto
var client = new ElasticClient();
var includeMinMax = true;

AggregationBase aggs = 
    new CardinalityAggregation("dedup", Infer.Field<MyDocument>(f => f.AddressHash))
    {
        PrecisionThreshold = 40000
    };

aggs &= new FilterAggregation("dontDedup")
    {
        Filter = new TermQuery
        {
            Field = Infer.Field<MyDocument>(f => f.AddressHash),
            Value = "0"
        }
    };

if (includeMinMax) 
{
    // && additional aggs
}

client.Search<MyDocument>(new SearchRequest<MyDocument>
{
   Aggregations = aggs
});

```

---

<div class="post-metadata">

**Author:** ![rgelb](https://avatars.discourse-cdn.com/v4/letter/r/da6949/32.png) [@rgelb](https://discuss.elastic.co/u/rgelb)\
**Post date:** [August 15, 2018, 7:09pm UTC](https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909/5 "2018-08-15T19:09:10Z")

</div>

Thank you for the detailed answer! I guess I didn't understand lambdas as well as I thought I did.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [September 12, 2018, 7:09pm UTC](https://discuss.elastic.co/t/is-it-possible-to-add-aggregations-piecemeal-to-the-nest-net-library/143909/6 "2018-09-12T19:09:13Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
