Skip to content

Commit 9fb1620

Browse files
committed
Partial implementation of the top hits aggregation
TODO: Still need to implement a top hits response object and handle deserialization in the AggregationConverter class.
1 parent 5766d38 commit 9fb1620

File tree

4 files changed

+137
-2
lines changed

4 files changed

+137
-2
lines changed

src/Nest/DSL/Aggregations/AggregationDescriptor.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ public interface IAggregationContainer
7575
[JsonProperty("value_count")]
7676
IValueCountAggregator ValueCount { get; set; }
7777

78+
[JsonProperty("top_hits")]
79+
ITopHitsAggregator TopHits { get; set; }
80+
7881
[JsonProperty("aggs")]
7982
[JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))]
8083
IDictionary<string, IAggregationContainer> Aggregations { get; set; }
@@ -98,14 +101,14 @@ public class AggregationContainer : IAggregationContainer
98101
private IRangeAggregator _range;
99102
private ITermsAggregator _terms;
100103
private ISignificantTermsAggregator _significantTerms;
104+
private ITopHitsAggregator _topHits;
101105
public IAverageAggregator Average { get; set; }
102106
public IValueCountAggregator ValueCount { get; set; }
103107
public IMaxAggregator Max { get; set; }
104108
public IMinAggregator Min { get; set; }
105109
public IStatsAggregator Stats { get; set; }
106110
public ISumAggregator Sum { get; set; }
107111
public IExtendedStatsAggregator ExtendedStats { get; set; }
108-
109112
public IDateHistogramAggregator DateHistogram
110113
{
111114
get { return _dateHistogram; }
@@ -196,6 +199,12 @@ public ISignificantTermsAggregator SignificantTerms
196199
set { _significantTerms = value; }
197200
}
198201

202+
public ITopHitsAggregator TopHits
203+
{
204+
get { return _topHits; }
205+
set { _topHits = value; }
206+
}
207+
199208
private void LiftAggregations(IBucketAggregator bucket)
200209
{
201210
if (bucket == null) return;
@@ -253,7 +262,9 @@ public class AggregationDescriptor<T> : IAggregationContainer
253262
ISignificantTermsAggregator IAggregationContainer.SignificantTerms { get; set; }
254263

255264
ITermsAggregator IAggregationContainer.Terms { get; set; }
256-
265+
266+
ITopHitsAggregator IAggregationContainer.TopHits { get; set; }
267+
257268
public AggregationDescriptor<T> Average(string name, Func<AverageAggregationDescriptor<T>, AverageAggregationDescriptor<T>> selector)
258269
{
259270
return _SetInnerAggregation(name, selector, (a, d) => a.Average = d);
@@ -375,6 +386,12 @@ public AggregationDescriptor<T> ValueCount(string name,
375386
return _SetInnerAggregation(name, selector, (a, d) => a.ValueCount = d);
376387
}
377388

389+
public AggregationDescriptor<T> TopHits(string name,
390+
Func<TopHitsAggregationDescriptor<T>, TopHitsAggregationDescriptor<T>> selector)
391+
{
392+
return _SetInnerAggregation(name, selector, (a, d) => a.TopHits = d);
393+
}
394+
378395
private AggregationDescriptor<T> _SetInnerAggregation<TAggregation>(
379396
string key,
380397
Func<TAggregation, TAggregation> selector
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using Nest.Resolvers.Converters;
2+
using Newtonsoft.Json;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
8+
namespace Nest
9+
{
10+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
11+
[JsonConverter(typeof(ReadAsTypeConverter<TopHitsAggregator>))]
12+
public interface ITopHitsAggregator : IMetricAggregator
13+
{
14+
[JsonProperty("from")]
15+
int? From { get; set; }
16+
17+
[JsonProperty("size")]
18+
int? Size { get; set; }
19+
20+
[JsonProperty("sort")]
21+
[JsonConverter(typeof(SortCollectionConverter))]
22+
IList<KeyValuePair<PropertyPathMarker, ISort>> Sort { get; set; }
23+
24+
[JsonProperty("_source")]
25+
ISourceFilter Source { get; set; }
26+
}
27+
28+
public class TopHitsAggregator : MetricAggregator, ITopHitsAggregator
29+
{
30+
public int? From { get; set; }
31+
public int? Size { get; set; }
32+
public IList<KeyValuePair<PropertyPathMarker, ISort>> Sort { get; set; }
33+
public ISourceFilter Source { get; set; }
34+
}
35+
36+
public class TopHitsAggregationDescriptor<T>
37+
: MetricAggregationBaseDescriptor<TopHitsAggregationDescriptor<T>, T>, ITopHitsAggregator
38+
where T : class
39+
{
40+
ITopHitsAggregator Self { get { return this; } }
41+
42+
int? ITopHitsAggregator.From { get; set; }
43+
44+
int? ITopHitsAggregator.Size { get; set; }
45+
46+
IList<KeyValuePair<PropertyPathMarker, ISort>> ITopHitsAggregator.Sort { get; set; }
47+
48+
ISourceFilter ITopHitsAggregator.Source { get; set; }
49+
50+
public TopHitsAggregationDescriptor<T> From(int from)
51+
{
52+
this.Self.From = from;
53+
return this;
54+
}
55+
56+
public TopHitsAggregationDescriptor<T> Size(int size)
57+
{
58+
this.Self.Size = size;
59+
return this;
60+
}
61+
62+
public TopHitsAggregationDescriptor<T> Sort(Func<SortFieldDescriptor<T>, IFieldSort> sortSelector)
63+
{
64+
sortSelector.ThrowIfNull("sortSelector");
65+
66+
if (Self.Sort == null)
67+
Self.Sort = new List<KeyValuePair<PropertyPathMarker, ISort>>();
68+
69+
var descriptor = sortSelector(new SortFieldDescriptor<T>());
70+
this.Self.Sort.Add(new KeyValuePair<PropertyPathMarker, ISort>(descriptor.Field, descriptor));
71+
72+
return this;
73+
}
74+
75+
public TopHitsAggregationDescriptor<T> Source(bool include = true)
76+
{
77+
if (!include)
78+
this.Self.Source = new SourceFilter { Exclude = new PropertyPathMarker[] { "*" } };
79+
else
80+
this.Self.Source = null;
81+
82+
return this;
83+
}
84+
85+
public TopHitsAggregationDescriptor<T> Source(Func<SearchSourceDescriptor<T>, SearchSourceDescriptor<T>> sourceSelector)
86+
{
87+
this.Self.Source = sourceSelector(new SearchSourceDescriptor<T>());
88+
return this;
89+
}
90+
}
91+
}

src/Nest/Nest.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@
207207
<Compile Include="Domain\Stats\PercolateStats.cs" />
208208
<Compile Include="Domain\Stats\PluginStats.cs" />
209209
<Compile Include="Domain\Stats\SegmentsStats.cs" />
210+
<Compile Include="DSL\Aggregations\TopHitsAggregationDescriptor.cs" />
210211
<Compile Include="DSL\CatIndicesDescriptor.cs" />
211212
<Compile Include="DSL\CatShardsDescriptor.cs" />
212213
<Compile Include="DSL\CatThreadPoolDescriptor.cs" />

src/Tests/Nest.Tests.Integration/Aggregations/MetricAggregationTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,31 @@ public void ValueCount()
119119
termBucket.Should().NotBeNull();
120120
termBucket.Value.Should().HaveValue();
121121
}
122+
123+
[Test]
124+
public void TopHits()
125+
{
126+
var results = this.Client.Search<ElasticsearchProject>(s => s
127+
.Size(0)
128+
.Aggregations(a => a
129+
.Terms("top-countries", t => t
130+
.Field(p => p.Country)
131+
.Size(3)
132+
.Aggregations(aa => aa
133+
.TopHits("top-country-hits", th => th
134+
.Sort(sort => sort
135+
.OnField(p => p.StartedOn)
136+
.Order(SortOrder.Descending)
137+
)
138+
.Source(src => src
139+
.Include(p => p.Name)
140+
)
141+
.Size(1)
142+
)
143+
)
144+
)
145+
)
146+
);
147+
}
122148
}
123149
}

0 commit comments

Comments
 (0)