Top Hits Aggregation Usageedit

Fluent DSL exampleedit

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
                            .Source("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)
                        .Field(p => p.SourceOnly)
                    )
                )
                .Size(1)
                .Version()
                .TrackScores()
                .Explain()
                .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
                        .Source("doc['numberOfCommits'].value * 2")

                    )

                )
                .DocValueFields(d => d
                    .Field(p => p.State)
                )
            )
        )
    )

Object Initializer syntax exampleedit

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", "sourceOnly" }
            },
            Size = 1,
            Version = true,
            TrackScores = true,
            Explain = true,
            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")
                    }
                },
            },
            DocValueFields = Infer.Fields<Project>(f => f.State)
        }
}

Example json output. 

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

Handling Responsesedit

response.ShouldBeValid();
var states = response.Aggregations.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<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");
    foreach (var project in projects)
        project.ShouldAdhereToSourceSerializerWhenSet();
}