Top Hits Aggregation Usageedit

Fluent DSL exampleedit

s => s
.Aggregations(a => a
    .Terms("states", t => t
        .Field(p => p.State)
        .Aggregations(aa => aa
            .TopHits("top_state_hits", th => th
                .Sort(srt => srt
                    .Field(sf => sf
                        .Field(p => p.StartedOn)
                        .Order(SortOrder.Descending)
                    )
                    .Script(ss => ss
                        .Type("number")
                        .Script(sss => sss
                            .Inline("Math.sin(34*(double)doc['numberOfCommits'].value)")
                            .Lang("painless")
                        )
                        .Order(SortOrder.Descending)
                    )
                )
                .Source(src => src
                    .Includes(fs => fs
                        .Field(p => p.Name)
                        .Field(p => p.LastActivity)
                    )
                )
                .Size(1)
                .Version()
                .TrackScores()
                .Explain()
                .FielddataFields(fd => fd
                    .Field(p => p.State)
                    .Field(p => p.NumberOfCommits)
                )
                .StoredFields(f => f
                    .Field(p => p.StartedOn)
                )
                .Highlight(h => h
                    .Fields(
                        hf => hf.Field(p => p.Tags),
                        hf => hf.Field(p => p.Description)
                    )
                )
                .ScriptFields(sfs => sfs
                    .ScriptField("commit_factor", sf => sf
                        .Inline("doc['numberOfCommits'].value * 2")
                        .Lang("groovy")
                    )
                )
                .DocValueFields(d => d
                    .Field(p => p.State)
                )
            )
        )
    )
)

Object Initializer syntax exampleedit

new SearchRequest<Project>
{
    Aggregations = new TermsAggregation("states")
    {
        Field = Field<Project>(p => p.State),
        Aggregations = new TopHitsAggregation("top_state_hits")
        {
            Sort = new List<ISort>
            {
                new SortField { Field = Field<Project>(p => p.StartedOn), Order = SortOrder.Descending },
                new ScriptSort
                {
                    Type = "number",
                    Script = new InlineScript("Math.sin(34*(double)doc['numberOfCommits'].value)") { Lang = "painless" },
                    Order = SortOrder.Descending
                },
            },
            Source = new SourceFilter
            {
                Includes = new[] { "name", "lastActivity" }
            },
            Size = 1,
            Version = true,
            TrackScores = true,
            Explain = true,
            FielddataFields = new[] { "state", "numberOfCommits" },
            StoredFields = new[] { "startedOn" },
            Highlight = new Highlight
            {
                Fields = new Dictionary<Field, IHighlightField>
                {
                    { Field<Project>(p => p.Tags), new HighlightField() },
                    { Field<Project>(p => p.Description), new HighlightField() }
                }
            },
            ScriptFields = new ScriptFields
            {
                {
                    "commit_factor", new ScriptField
                    {
                        Script = new InlineScript("doc['numberOfCommits'].value * 2") { Lang = "groovy" }
                    }
                }
            },
            DocValueFields = Fields<Project>(f => f.State)
        }
    }
}

Example json output.

{
  "aggs": {
    "states": {
      "terms": {
        "field": "state"
      },
      "aggs": {
        "top_state_hits": {
          "top_hits": {
            "sort": [
              {
                "startedOn": {
                  "order": "desc"
                }
              },
              {
                "_script": {
                  "type": "number",
                  "script": {
                    "lang": "painless",
                    "inline": "Math.sin(34*(double)doc['numberOfCommits'].value)"
                  },
                  "order": "desc"
                }
              }
            ],
            "_source": {
              "includes": [
                "name",
                "lastActivity"
              ]
            },
            "size": 1,
            "version": true,
            "track_scores": true,
            "explain": true,
            "fielddata_fields": [
              "state",
              "numberOfCommits"
            ],
            "stored_fields": [
              "startedOn"
            ],
            "highlight": {
              "fields": {
                "tags": {},
                "description": {}
              }
            },
            "script_fields": {
              "commit_factor": {
                "script": {
                  "inline": "doc['numberOfCommits'].value * 2",
                  "lang": "groovy"
                }
              }
            },
            "docvalue_fields": [
              "state"
            ]
          }
        }
      }
    }
  }
}

Handling Responsesedit

response.ShouldBeValid();
var states = response.Aggs.Terms("states");
states.Should().NotBeNull();
states.Buckets.Should().NotBeNullOrEmpty();
foreach (var state in states.Buckets)
{
    state.Key.Should().NotBeNullOrEmpty();
    state.DocCount.Should().BeGreaterThan(0);
    var topStateHits = state.TopHits("top_state_hits");
    topStateHits.Should().NotBeNull();
    topStateHits.Total.Should().BeGreaterThan(0);
    var hits = topStateHits.Hits<Project>();
    hits.Should().NotBeNullOrEmpty();
    hits.All(h => h.Explanation != null).Should().BeTrue();
    hits.All(h => h.Version.HasValue).Should().BeTrue();
    hits.All(h => h.Fields.ValuesOf<StateOfBeing>("state").Any()).Should().BeTrue();
    hits.All(h => h.Fields.ValuesOf<int>("numberOfCommits").Any()).Should().BeTrue();
    hits.All(h => h.Fields.ValuesOf<int>("commit_factor").Any()).Should().BeTrue();
    hits.All(h => h.Fields.ValuesOf<DateTime>("startedOn").Any()).Should().BeTrue();
    var projects = topStateHits.Documents<Project>();
    projects.Should().NotBeEmpty();
    projects.Should().OnlyContain(p => !string.IsNullOrWhiteSpace(p.Name), "source filter included name");
    projects.Should().OnlyContain(p => string.IsNullOrWhiteSpace(p.Description), "source filter does NOT include description");
}