1
votes

I'm using the composite and terms aggregations to get grouped results based on a given field. I'm also using Cardinality aggregation to get the overall count of the aggregation buckets.

The below is my request query I'm sending to get the corresponding response:

Request:

"aggs": {
    "myfield_comp_agg": {
      "aggs": {
        "myfield": {
          "aggs": {
            "myfield_tophits": {
              "top_hits": {
                "size": 1
              }
            }
          },
          "terms": {
            "field": "myfield",
            "size": 10
          }
        }
      },
      "composite": {
        "after": {
          "myfield_comp_terms_agg": ""
        },
        "sources": [
          {
            "myfield_comp_terms_agg": {
              "terms": {
                "field": "myfield"
              }
            }
          }
        ]
      }
    },
    "Count_agg": {
      "cardinality": {
        "field": "myfield"
      }
    }
  }

Response:

{
  ...,
  "aggregations" : {
    "Count_agg" : {
      "value" : 33
    },
    "myfield_comp_agg" : {
      "after_key" : {
        "myfield_comp_terms_agg" : "value10"
      },
      "buckets" : [
        {
          "key" : {
            "DocId_comp_terms_agg" : "value1"
          },
          "doc_count" : 1,
          "DocId" : {...}
        },
        {...},
        {...},
        {...}
      ]
    }
  }
}

I used Kibana to check the query and it works fine for me.

However, I'm not sure how to use this cardinality aggregator in my NEST object syntax.

Here is my code:

var termsAggregation = new TermsAggregation(GetTermsAggregationName(aggregationField)) {
                Field = aggregationField,
                Size = takeCount
            };

            var topHitsAggregation = new TopHitsAggregation(GetTopHitsAggregationName(aggregationField)) {
                Size = aggregationFieldCount
            };                
            var termsAggregationContainer = new AggregationContainer {
                Terms = termsAggregation,
                Aggregations = topHitsAggregation
            };
            var subAggregations = new Dictionary<string, IAggregationContainer>() {
                { aggregationField, termsAggregationContainer}
            };

            var compositeKey = new Dictionary<string, object>() {
                { GetCompositeTermsAggregationName(aggregationField), aggregationSkipValue }
            };
            var termsSource = new TermsCompositeAggregationSource(GetCompositeTermsAggregationName(aggregationField)) {
                Field = aggregationField
            };
            var compositeAggregation = new CompositeAggregation(GetCompositeAggregationName(aggregationField)) {
                After = new CompositeKey(compositeKey),
                Sources = new List<TermsCompositeAggregationSource> { termsSource },
                Aggregations = subAggregations
            };

var searchRequest = new SearchRequest(request.IndexName)
            {
                From = request.SkipCount,
                Size = request.TakeCount
            };
searchRequest.Aggregations = compositeAggregation;
ElasticSearchClient.Search<T>(searchRequest);

I'd greatly appreciate any help.

1
Answered your same question here: discuss.elastic.co/t/…Russ Cam

1 Answers

0
votes

Answer as posted by Russ in the comment.

Take a look at the writing aggregations documentation for the client; it has some suggestions for more terse object initializer syntax, such as using AggregationDictionary and &&ing aggregations to combine them.

Here's an example that matches the request query

var client = new ElasticClient();   

AggregationDictionary aggs = new CompositeAggregation("myfield_comp_agg")
{
    After = new CompositeKey(new Dictionary<string, object>
    {
        { "myfield_comp_terms_agg", string.Empty }
    }),
    Sources = new ICompositeAggregationSource[] 
    {
        new TermsCompositeAggregationSource("myfield_comp_terms_agg")
        {
            Field = "myfield"
        }
    },
    Aggregations = new TermsAggregation("myfield")
    {
        Field = "myfield",
        Size = 10,
        Aggregations = new TopHitsAggregation("myfield_tophits")
        {
            Size = 1
        }
    }
} && new CardinalityAggregation("Count_agg", "myfield");

var searchRequest = new SearchRequest("my_index")
{
    Aggregations = aggs
};

var searchResponse = client.Search<object>(searchRequest);

Thanks for the help. It worked perfectly.