From 47bc17849c04aa8c2d0dc0b61e83c73bf53e748d Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 27 Feb 2014 17:01:05 +0100 Subject: [PATCH 1/7] started on aggregations finally :) --- .../DSL/Aggregations/AggregationDescriptor.cs | 21 +++++ .../AverageAggregationDescriptor.cs | 16 ++++ .../BucketAggregationBaseDescriptor.cs | 39 +++++++++ .../DateRangeAggregationDescriptor.cs | 46 ++++++++++ .../ExtendedStatsAggregationDescriptor.cs | 8 ++ .../Aggregations/IAggregationDescriptor.cs | 7 ++ .../Ip4RangeAggregationDescriptor.cs | 37 ++++++++ .../Aggregations/MaxAggregationDescriptor.cs | 16 ++++ .../MetricAggregationBaseDescriptor.cs | 85 +++++++++++++++++++ .../Aggregations/MinAggregationDescriptor.cs | 16 ++++ .../NestedAggregationDescriptor.cs | 35 ++++++++ .../RangeAggregationDescriptor.cs | 55 ++++++++++++ .../StatsAggregationDescriptor.cs | 28 ++++++ .../Aggregations/SumAggregationDescriptor.cs | 16 ++++ .../TermsAggregationDescriptor.cs | 83 ++++++++++++++++++ .../ValueCountAggregationDescriptor.cs | 8 ++ src/Nest/DSL/Facets/DateExpressionRange.cs | 25 ++++++ src/Nest/DSL/Facets/Ip4Range.cs | 17 ++++ src/Nest/DSL/Facets/Range.cs | 4 +- .../Domain/Mapping/Types/StringMapping.cs | 1 + src/Nest/Enums/ExecutionHint.cs | 17 ++++ src/Nest/Enums/FieldIndexOption.cs | 2 +- src/Nest/Nest.csproj | 8 ++ .../Converters/YesNoBoolConverter.cs | 2 +- .../Nest.Tests.Integration.csproj | 1 + 25 files changed, 589 insertions(+), 4 deletions(-) create mode 100644 src/Nest/DSL/Aggregations/AggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/IAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Facets/DateExpressionRange.cs create mode 100644 src/Nest/DSL/Facets/Ip4Range.cs create mode 100644 src/Nest/Enums/ExecutionHint.cs diff --git a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs new file mode 100644 index 00000000000..81e57b050b7 --- /dev/null +++ b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace Nest.DSL.Aggregations +{ + public class AggregationDescriptor + where T : class + { + private readonly IDictionary _aggregations = + new Dictionary(); + + public AggregationDescriptor Average( + Func, AverageAggregationDescriptor> selector) + { + var agg = selector(new AverageAggregationDescriptor()); + if (agg == null) return this; + this._aggregations.Add("avg", agg); + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs new file mode 100644 index 00000000000..1b6f14eda62 --- /dev/null +++ b/src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class AverageAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } +} diff --git a/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs new file mode 100644 index 00000000000..8b8aa0fe136 --- /dev/null +++ b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public abstract class BucketAggregationBaseDescriptor: IAggregationDescriptor + where TBucketAggregation : BucketAggregationBaseDescriptor + where T : class + { + [JsonProperty("aggs")] + internal AggregationDescriptor _Aggregations; + + public TBucketAggregation Aggregations(Func, AggregationDescriptor> selector) + { + this._Aggregations = selector(new AggregationDescriptor()); + return (TBucketAggregation)this; + } + } + + public class FilterAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("filter")] + internal BaseFilter _Filter { get; set; } + + public FilterAggregationDescriptor Filter(Func, BaseFilter> selector) + { + this._Filter = selector(new FilterDescriptor()); + return this; + } + } + public class GlobalAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("global")] internal readonly object _Global = new object {}; + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs new file mode 100644 index 00000000000..69302e859db --- /dev/null +++ b/src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class DateRangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public DateRangeAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public DateRangeAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty("format")] + internal string _Format { get; set; } + + public DateRangeAggregationDescriptor Format(string format) + { + this._Format = format; + return this; + } + + [JsonProperty(PropertyName = "ranges")] + internal IEnumerable _Ranges { get; set; } + + public DateRangeAggregationDescriptor Ranges(params Func[] ranges) + { + var newRanges = from range in ranges let r = new DateExpressionRange() select range(r); + this._Ranges = newRanges; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs new file mode 100644 index 00000000000..28d4fc1bc10 --- /dev/null +++ b/src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs @@ -0,0 +1,8 @@ +namespace Nest.DSL.Aggregations +{ + public class ExtendedStatsAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/IAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/IAggregationDescriptor.cs new file mode 100644 index 00000000000..feec3faacd7 --- /dev/null +++ b/src/Nest/DSL/Aggregations/IAggregationDescriptor.cs @@ -0,0 +1,7 @@ +namespace Nest.DSL.Aggregations +{ + public interface IAggregationDescriptor + { + + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs new file mode 100644 index 00000000000..1ef596c0449 --- /dev/null +++ b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class Ip4RangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public Ip4RangeAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public Ip4RangeAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty(PropertyName = "ranges")] + internal IEnumerable _Ranges { get; set; } + + public Ip4RangeAggregationDescriptor Ranges(params string[] ranges) + { + var newRanges = from range in ranges let r = new Ip4Range().Mask(range) select r; + this._Ranges = newRanges; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs new file mode 100644 index 00000000000..b82e3586316 --- /dev/null +++ b/src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class MaxAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } +} diff --git a/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs b/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs new file mode 100644 index 00000000000..c5c71793731 --- /dev/null +++ b/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + + public class AggregationDescriptor + where T : class + { + private readonly IDictionary _aggregations = + new Dictionary(); + + public AggregationDescriptor Average( + Func, AverageAggregationDescriptor> selector) + { + var agg = selector(new AverageAggregationDescriptor()); + if (agg == null) return this; + this._aggregations.Add("avg", agg); + return this; + } + } + + public interface IAggregationDescriptor + { + + } + + public abstract class MetricAggregationBaseDescriptor : IAggregationDescriptor + where TMetricAggregation : MetricAggregationBaseDescriptor + where T : class + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public TMetricAggregation Field(string field) + { + this._Field = field; + return (TMetricAggregation)this; + } + + public TMetricAggregation Field(Expression> field) + { + this._Field = field; + return (TMetricAggregation) this; + } + + [JsonProperty("script")] + internal string _Script { get; set; } + + public TMetricAggregation Script(string script) + { + this._Script = script; + return (TMetricAggregation)this; + } + + [JsonProperty("params")] + internal FluentDictionary _Params { get; set; } + + public TMetricAggregation Params(Func, FluentDictionary> paramSelector) + { + this._Params = paramSelector(new FluentDictionary()); + return (TMetricAggregation) this; + } + } + + public abstract class BucketAggregationBaseDescriptor: IAggregationDescriptor + where TBucketAggregation : BucketAggregationBaseDescriptor + where T : class + { + [JsonProperty("aggs")] + internal AggregationDescriptor _Aggregations; + + public TBucketAggregation Aggregations(Func, AggregationDescriptor> selector) + { + this._Aggregations = selector(new AggregationDescriptor()); + return (TBucketAggregation)this; + } + + } +} diff --git a/src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs new file mode 100644 index 00000000000..197f2624cb6 --- /dev/null +++ b/src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class MinAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } +} diff --git a/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs new file mode 100644 index 00000000000..2f441dde6a5 --- /dev/null +++ b/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs @@ -0,0 +1,35 @@ +using System; +using System.Linq.Expressions; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class NestedAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class + { + internal class NestedAgg + { + [JsonProperty("path")] + internal PropertyPathMarker _Path; + } + + [JsonProperty("nested")] + internal NestedAgg _Nested; + + + public NestedAggregationDescriptor Path(string path) + { + this._Nested = new NestedAgg(); + this._Nested._Path = path; + return this; + } + + public NestedAggregationDescriptor Path(Expression> path) + { + this._Nested = new NestedAgg(); + this._Nested._Path = path; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs new file mode 100644 index 00000000000..a87b4b15f93 --- /dev/null +++ b/src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class RangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public RangeAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public RangeAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty("script")] + internal string _Script { get; set; } + + public RangeAggregationDescriptor Script(string script) + { + this._Script = script; + return this; + } + + [JsonProperty("params")] + internal FluentDictionary _Params { get; set; } + + public RangeAggregationDescriptor Params(Func, FluentDictionary> paramSelector) + { + this._Params = paramSelector(new FluentDictionary()); + return this; + } + + [JsonProperty(PropertyName = "ranges")] + internal IEnumerable> _Ranges { get; set; } + + public RangeAggregationDescriptor Ranges(params Func, Range>[] ranges) + { + var newRanges = from range in ranges let r = new Range() select range(r); + this._Ranges = newRanges; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs new file mode 100644 index 00000000000..87178d79ef0 --- /dev/null +++ b/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using Nest.Resolvers; + +namespace Nest.DSL.Aggregations +{ + public class StatsAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } + + public class ExtendedStatsAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } + + public class ValueCountAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } +} diff --git a/src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs new file mode 100644 index 00000000000..6afb051cc10 --- /dev/null +++ b/src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class SumAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } +} diff --git a/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs new file mode 100644 index 00000000000..07f36e9eefb --- /dev/null +++ b/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using Elasticsearch.Net; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class TermsAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("size")] + internal int? _Size { get; set; } + + public TermsAggregationDescriptor Size(int size) + { + this._Size = size; + return this; + } + + [JsonProperty("shard_size")] + internal int? _ShardSize { get; set; } + + public TermsAggregationDescriptor ShardSize(int shardSize) + { + this._ShardSize = shardSize; + return this; + } + + [JsonProperty("min_doc_count")] + internal int? _MinimumDocumentCount { get; set; } + + public TermsAggregationDescriptor MinimumDocumentCount(int minimumDocumentCount) + { + this._MinimumDocumentCount = minimumDocumentCount; + return this; + } + + [JsonProperty("execution_hit")] + internal TermsAggregationExecutionHint? _ExecutionHint { get; set; } + + public TermsAggregationDescriptor ExecutionHint(TermsAggregationExecutionHint executionHint) + { + this._ExecutionHint = executionHint; + return this; + } + + [JsonProperty("order")] + internal IDictionary _Order { get; set; } + + public TermsAggregationDescriptor OrderAscending(string key) + { + this._Order = new Dictionary { {key, "asc"}}; + return this; + } + + public TermsAggregationDescriptor OrderDescending(string key) + { + this._Order = new Dictionary { {key, "asc"}}; + return this; + } + + [JsonProperty("include")] + internal IDictionary _Include { get; set; } + + public TermsAggregationDescriptor Include(string includePattern, string regexFlags = null) + { + this._Include = new Dictionary { {"pattern", includePattern}}; + if (!regexFlags.IsNullOrEmpty()) + this._Include.Add("pattern", regexFlags); + return this; + } + + [JsonProperty("exclude")] + internal IDictionary _Exclude { get; set; } + + public TermsAggregationDescriptor Exclude(string excludePattern, string regexFlags = null) + { + this._Exclude = new Dictionary { {"pattern", excludePattern}}; + if (!regexFlags.IsNullOrEmpty()) + this._Exclude.Add("pattern", regexFlags); + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs new file mode 100644 index 00000000000..f6e621b8ce7 --- /dev/null +++ b/src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs @@ -0,0 +1,8 @@ +namespace Nest.DSL.Aggregations +{ + public class ValueCountAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Facets/DateExpressionRange.cs b/src/Nest/DSL/Facets/DateExpressionRange.cs new file mode 100644 index 00000000000..14e5ec6ed47 --- /dev/null +++ b/src/Nest/DSL/Facets/DateExpressionRange.cs @@ -0,0 +1,25 @@ +using System; +using Newtonsoft.Json; + +namespace Nest +{ + public class DateExpressionRange + { + [JsonProperty(PropertyName = "from")] + internal string _From { get; set; } + + [JsonProperty(PropertyName = "to")] + internal string _To { get; set; } + + public DateExpressionRange From(string value) + { + this._From = value; + return this; + } + public DateExpressionRange To(string value) + { + this._To = value; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Facets/Ip4Range.cs b/src/Nest/DSL/Facets/Ip4Range.cs new file mode 100644 index 00000000000..38663567fa4 --- /dev/null +++ b/src/Nest/DSL/Facets/Ip4Range.cs @@ -0,0 +1,17 @@ +using System; +using Newtonsoft.Json; + +namespace Nest +{ + public class Ip4Range + { + [JsonProperty(PropertyName = "mask")] + internal string _Mask { get; set; } + + public Ip4Range Mask(string value) + { + this._Mask = value; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Facets/Range.cs b/src/Nest/DSL/Facets/Range.cs index 2f315316f40..bdb03411f8c 100644 --- a/src/Nest/DSL/Facets/Range.cs +++ b/src/Nest/DSL/Facets/Range.cs @@ -10,10 +10,10 @@ namespace Nest public class Range where T : struct { [JsonProperty(PropertyName = "from")] - internal Nullable _From { get; set; } + internal T? _From { get; set; } [JsonProperty(PropertyName = "to")] - internal Nullable _To { get; set; } + internal T? _To { get; set; } public Range From(T value) { diff --git a/src/Nest/Domain/Mapping/Types/StringMapping.cs b/src/Nest/Domain/Mapping/Types/StringMapping.cs index adf1bdec1df..4ed51b47304 100644 --- a/src/Nest/Domain/Mapping/Types/StringMapping.cs +++ b/src/Nest/Domain/Mapping/Types/StringMapping.cs @@ -28,6 +28,7 @@ public class StringMapping : IElasticType, IElasticCoreType [JsonProperty("analyzer")] public string Analyzer { get; set; } + [JsonProperty("store"), JsonConverter(typeof(YesNoBoolConverter))] public bool? Store { get; set; } [JsonProperty("index"), JsonConverter(typeof(StringEnumConverter))] diff --git a/src/Nest/Enums/ExecutionHint.cs b/src/Nest/Enums/ExecutionHint.cs new file mode 100644 index 00000000000..11874128563 --- /dev/null +++ b/src/Nest/Enums/ExecutionHint.cs @@ -0,0 +1,17 @@ +namespace Nest +{ + /// + /// Determines how the terms aggregation is executed + /// + public enum TermsAggregationExecutionHint + { + /// + /// Order by using field values directly in order to aggregate data per-bucket + /// + map, + /// + /// Order by using ordinals of the field values instead of the values themselves + /// + ordinals + } +} \ No newline at end of file diff --git a/src/Nest/Enums/FieldIndexOption.cs b/src/Nest/Enums/FieldIndexOption.cs index 1cc8fb45df8..61f84f940bb 100644 --- a/src/Nest/Enums/FieldIndexOption.cs +++ b/src/Nest/Enums/FieldIndexOption.cs @@ -5,5 +5,5 @@ public enum FieldIndexOption analyzed, not_analyzed, no - } + } } diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index d46d237f36c..f5eb5683c77 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -111,6 +111,12 @@ + + + + + + @@ -168,6 +174,7 @@ + @@ -694,6 +701,7 @@ Elasticsearch.Net + diff --git a/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs b/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs index a790f6b5708..4e517f70575 100644 --- a/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs +++ b/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs @@ -19,7 +19,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var v = reader.Value.ToString(); - return reader.Value != null && (v == "yes" || v == "True"); + return reader.Value != null && (v == "yes" || v == " True"); } public override bool CanConvert(Type objectType) diff --git a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj index 0627570b52b..53103a8eced 100644 --- a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj +++ b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj @@ -125,6 +125,7 @@ + From 0eff7b6b00a15bdb56a64a90ba717f4a8a3e8e1e Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 27 Feb 2014 20:08:46 +0100 Subject: [PATCH 2/7] all aggregation descriptors are now mapped --- .../DSL/Aggregations/AggregationDescriptor.cs | 165 +++++++++++++++++- .../BucketAggregationBaseDescriptor.cs | 18 -- .../DateHistogramAggregationDescriptor.cs | 140 +++++++++++++++ .../FilterAggregationDescriptor.cs | 18 ++ .../GeoDistanceAggregationDescriptor.cs | 72 ++++++++ .../GeoHashAggregationDescriptor.cs | 55 ++++++ .../GlobalAggregationDescriptor.cs | 10 ++ .../HistogramAggregationDescriptor.cs | 80 +++++++++ .../MetricAggregationBaseDescriptor.cs | 37 ---- .../MissingAggregationDescriptor.cs | 28 +++ .../StatsAggregationDescriptor.cs | 12 -- .../TermsAggregationDescriptor.cs | 37 +++- src/Nest/Enums/GeoDistanceType.cs | 13 ++ src/Nest/Enums/GeoHashPrecision.cs | 73 ++++++++ src/Nest/Nest.csproj | 17 +- 15 files changed, 701 insertions(+), 74 deletions(-) create mode 100644 src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs create mode 100644 src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs create mode 100644 src/Nest/Enums/GeoDistanceType.cs create mode 100644 src/Nest/Enums/GeoHashPrecision.cs diff --git a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs index 81e57b050b7..298240e04b3 100644 --- a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Reflection; +using Newtonsoft.Json; namespace Nest.DSL.Aggregations { @@ -9,13 +11,166 @@ public class AggregationDescriptor private readonly IDictionary _aggregations = new Dictionary(); - public AggregationDescriptor Average( - Func, AverageAggregationDescriptor> selector) + public AverageAggregationDescriptor _Average { get; set; } + public AggregationDescriptor Average(Func, AverageAggregationDescriptor> selector) { - var agg = selector(new AverageAggregationDescriptor()); - if (agg == null) return this; - this._aggregations.Add("avg", agg); + this._Average = selector(new AverageAggregationDescriptor()); return this; } + + [JsonProperty("date_histogram")] + public DateHistogramAggregationDescriptor _DateHistogram { get; set; } + public AggregationDescriptor DateHistogram( + Func, DateHistogramAggregationDescriptor> selector) + { + this._DateHistogram = selector(new DateHistogramAggregationDescriptor()); + return this; + } + + [JsonProperty("date_range")] + public DateRangeAggregationDescriptor _DateRange { get; set; } + public AggregationDescriptor DateRange( + Func, DateRangeAggregationDescriptor> selector) + { + this._DateRange = selector(new DateRangeAggregationDescriptor()); + return this; + } + + [JsonProperty("extended_stats")] + public ExtendedStatsAggregationDescriptor _ExtendedStats { get; set; } + public AggregationDescriptor ExtendedStats( + Func, ExtendedStatsAggregationDescriptor> selector) + { + this._ExtendedStats = selector(new ExtendedStatsAggregationDescriptor()); + return this; + } + + [JsonProperty("filter")] + public FilterAggregationDescriptor _Filter { get; set; } + public AggregationDescriptor Filter( + Func, FilterAggregationDescriptor> selector) + { + this._Filter = selector(new FilterAggregationDescriptor()); + return this; + } + + [JsonProperty("geo_distance")] + public GeoDistanceAggregationDescriptor _GeoDistance { get; set; } + public AggregationDescriptor GeoDistance( + Func, GeoDistanceAggregationDescriptor> selector) + { + this._GeoDistance = selector(new GeoDistanceAggregationDescriptor()); + return this; + } + + [JsonProperty("geo_hash")] + public GeoHashAggregationDescriptor _GeoHash { get; set; } + public AggregationDescriptor GeoHash( + Func, GeoHashAggregationDescriptor> selector) + { + this._GeoHash = selector(new GeoHashAggregationDescriptor()); + return this; + } + + [JsonProperty("histogram")] + public HistogramAggregationDescriptor _Histogram { get; set; } + public AggregationDescriptor Histogram( + Func, HistogramAggregationDescriptor> selector) + { + this._Histogram = selector(new HistogramAggregationDescriptor()); + return this; + } + + [JsonProperty("global")] + public GlobalAggregationDescriptor _Global { get; set; } + public AggregationDescriptor Global( + Func, GlobalAggregationDescriptor> selector) + { + this._Global = selector(new GlobalAggregationDescriptor()); + return this; + } + + [JsonProperty("ip4_range")] + public Ip4RangeAggregationDescriptor _Ip4Range { get; set; } + public AggregationDescriptor Ip4Range( + Func, Ip4RangeAggregationDescriptor> selector) + { + this._Ip4Range = selector(new Ip4RangeAggregationDescriptor()); + return this; + } + + [JsonProperty("max")] + public MaxAggregationDescriptor _Max { get; set; } + public AggregationDescriptor Max(Func, MaxAggregationDescriptor> selector) + { + this._Max = selector(new MaxAggregationDescriptor()); + return this; + } + + [JsonProperty("min")] + public MinAggregationDescriptor _Min { get; set; } + public AggregationDescriptor Min(Func, MinAggregationDescriptor> selector) + { + this._Min = selector(new MinAggregationDescriptor()); + return this; + } + + [JsonProperty("missing")] + public MissingAggregationDescriptor _Missing { get; set; } + public AggregationDescriptor Missing(Func, MissingAggregationDescriptor> selector) + { + this._Missing = selector(new MissingAggregationDescriptor()); + return this; + } + + [JsonProperty("nested")] + public NestedAggregationDescriptor _Nested { get; set; } + public AggregationDescriptor Nested(Func, NestedAggregationDescriptor> selector) + { + this._Nested = selector(new NestedAggregationDescriptor()); + return this; + } + + [JsonProperty("range")] + public RangeAggregationDescriptor _Range { get; set; } + public AggregationDescriptor Range(Func, RangeAggregationDescriptor> selector) + { + this._Range = selector(new RangeAggregationDescriptor()); + return this; + } + + [JsonProperty("stats")] + public StatsAggregationDescriptor _Stats { get; set; } + public AggregationDescriptor Stats(Func, StatsAggregationDescriptor> selector) + { + this._Stats = selector(new StatsAggregationDescriptor()); + return this; + } + + [JsonProperty("sum")] + public SumAggregationDescriptor _Sum { get; set; } + public AggregationDescriptor Sum(Func, SumAggregationDescriptor> selector) + { + this._Sum = selector(new SumAggregationDescriptor()); + return this; + } + + [JsonProperty("terms")] + public TermsAggregationDescriptor _Terms { get; set; } + public AggregationDescriptor Terms(Func, TermsAggregationDescriptor> selector) + { + this._Terms = selector(new TermsAggregationDescriptor()); + return this; + } + + [JsonProperty("value_count")] + public ValueCountAggregationDescriptor _ValueCount { get; set; } + public AggregationDescriptor ValueCount( + Func, ValueCountAggregationDescriptor> selector) + { + this._ValueCount = selector(new ValueCountAggregationDescriptor()); + return this; + } + } } \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs index 8b8aa0fe136..96a43e6a29c 100644 --- a/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs +++ b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs @@ -18,22 +18,4 @@ public TBucketAggregation Aggregations(Func, Aggregatio return (TBucketAggregation)this; } } - - public class FilterAggregationDescriptor : BucketAggregationBaseDescriptor, T> - where T : class - { - [JsonProperty("filter")] - internal BaseFilter _Filter { get; set; } - - public FilterAggregationDescriptor Filter(Func, BaseFilter> selector) - { - this._Filter = selector(new FilterDescriptor()); - return this; - } - } - public class GlobalAggregationDescriptor : BucketAggregationBaseDescriptor, T> - where T : class - { - [JsonProperty("global")] internal readonly object _Global = new object {}; - } } \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs new file mode 100644 index 00000000000..ac4babe8d1f --- /dev/null +++ b/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using Elasticsearch.Net; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class DateHistogramAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public DateHistogramAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public DateHistogramAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty("script")] + internal string _Script { get; set; } + + public DateHistogramAggregationDescriptor Script(string script) + { + this._Script = script; + return this; + } + + [JsonProperty("params")] + internal FluentDictionary _Params { get; set; } + + public DateHistogramAggregationDescriptor Params(Func, FluentDictionary> paramSelector) + { + this._Params = paramSelector(new FluentDictionary()); + return this; + } + + [JsonProperty("interval")] + internal string _Interval { get; set; } + + public DateHistogramAggregationDescriptor Interval(string interval) + { + this._Interval = interval; + return this; + } + + [JsonProperty("min_doc_count")] + internal int? _MinimumDocumentCount { get; set; } + + public DateHistogramAggregationDescriptor MinimumDocumentCount(int minimumDocumentCount) + { + this._MinimumDocumentCount = minimumDocumentCount; + return this; + } + + [JsonProperty("pre_zone")] + internal string _PreZone { get; set; } + + public DateHistogramAggregationDescriptor PreZone(string preZone) + { + this._PreZone = preZone; + return this; + } + + [JsonProperty("post_zone")] + internal string _PostZone { get; set; } + + public DateHistogramAggregationDescriptor PostZone(string postZone) + { + this._PostZone = postZone; + return this; + } + + [JsonProperty("time_zone")] + internal string _TimeZone { get; set; } + + public DateHistogramAggregationDescriptor TimeZone(string timeZone) + { + this._TimeZone = timeZone; + return this; + } + [JsonProperty("pre_zone_adjust_large_interval")] + internal bool? _PreZoneAdjustLargeInterval { get; set; } + + public DateHistogramAggregationDescriptor PreZoneAdjustLargeInterval(bool adjustLargeInterval = true) + { + this._PreZoneAdjustLargeInterval = adjustLargeInterval; + return this; + } + [JsonProperty("factor")] + internal int? _Factor { get; set; } + + public DateHistogramAggregationDescriptor Interval(int factor) + { + this._Factor = factor; + return this; + } + + [JsonProperty("pre_offset")] + internal string _PreOffset { get; set; } + + public DateHistogramAggregationDescriptor PreOffset(string preOffset) + { + this._PreOffset = preOffset; + return this; + } + [JsonProperty("post_offset")] + internal string _PostOffset { get; set; } + + public DateHistogramAggregationDescriptor PostOffset(string postOffset) + { + this._PostOffset = postOffset; + return this; + } + + [JsonProperty("order")] + internal IDictionary _Order { get; set; } + + public DateHistogramAggregationDescriptor OrderAscending(string key) + { + this._Order = new Dictionary { {key, "asc"}}; + return this; + } + + public DateHistogramAggregationDescriptor OrderDescending(string key) + { + this._Order = new Dictionary { {key, "asc"}}; + return this; + } + + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs new file mode 100644 index 00000000000..2a84e7b7cc0 --- /dev/null +++ b/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs @@ -0,0 +1,18 @@ +using System; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class FilterAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("filter")] + internal BaseFilter _Filter { get; set; } + + public FilterAggregationDescriptor Filter(Func, BaseFilter> selector) + { + this._Filter = selector(new FilterDescriptor()); + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs new file mode 100644 index 00000000000..94df37dfeb7 --- /dev/null +++ b/src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class GeoDistanceAggregationDescriptor : BucketAggregationBaseDescriptor, T> + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public GeoDistanceAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public GeoDistanceAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty("origin")] + internal string _Origin { get; set; } + + public GeoDistanceAggregationDescriptor Origin(double Lat, double Lon) + { + var c = CultureInfo.InvariantCulture; + this._Origin = "{0}, {1}".F(Lat.ToString(c), Lon.ToString(c)); + return this; + } + + public GeoDistanceAggregationDescriptor Origin(string geoHash) + { + this._Origin = geoHash; + return this; + } + + [JsonProperty("unit")] + internal GeoUnit? _Unit { get; set; } + + public GeoDistanceAggregationDescriptor Unit(GeoUnit unit) + { + this._Unit = unit; + return this; + } + + [JsonProperty("distance_type")] + internal GeoDistanceType? _DistanceType { get; set; } + + public GeoDistanceAggregationDescriptor DistanceType(GeoDistanceType geoDistanceType) + { + this._DistanceType = geoDistanceType; + return this; + } + + [JsonProperty(PropertyName = "ranges")] + internal IEnumerable> _Ranges { get; set; } + + public GeoDistanceAggregationDescriptor Ranges(params Func, Range>[] ranges) + { + var newRanges = from range in ranges let r = new Range() select range(r); + this._Ranges = newRanges; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs new file mode 100644 index 00000000000..af08add4a7b --- /dev/null +++ b/src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Linq.Expressions; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class GeoHashAggregationDescriptor : BucketAggregationBaseDescriptor, T> + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public GeoHashAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public GeoHashAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty("size")] + internal int? _Size { get; set; } + + public GeoHashAggregationDescriptor Size(int size) + { + this._Size = size; + return this; + } + + [JsonProperty("shard_size")] + internal int? _ShardSize { get; set; } + + public GeoHashAggregationDescriptor ShardSize(int shardSize) + { + this._ShardSize = shardSize; + return this; + } + + [JsonProperty("precision")] + internal GeoHashPrecision? _Precision { get; set; } + + public GeoHashAggregationDescriptor GeoHashPrecision(GeoHashPrecision precision) + { + this._Precision = precision; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs new file mode 100644 index 00000000000..4c034d07ebb --- /dev/null +++ b/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class GlobalAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("global")] internal readonly object _Global = new object {}; + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs new file mode 100644 index 00000000000..33eb678652b --- /dev/null +++ b/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using Elasticsearch.Net; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class HistogramAggregationDescriptor : MetricAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public HistogramAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public HistogramAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty("script")] + internal string _Script { get; set; } + + public HistogramAggregationDescriptor Script(string script) + { + this._Script = script; + return this; + } + + [JsonProperty("params")] + internal FluentDictionary _Params { get; set; } + + public HistogramAggregationDescriptor Params(Func, FluentDictionary> paramSelector) + { + this._Params = paramSelector(new FluentDictionary()); + return this; + } + + [JsonProperty("interval")] + internal double? _Interval { get; set; } + + public HistogramAggregationDescriptor Interval(double interval) + { + this._Interval = interval; + return this; + } + + [JsonProperty("min_doc_count")] + internal int? _MinimumDocumentCount { get; set; } + + public HistogramAggregationDescriptor MinimumDocumentCount(int minimumDocumentCount) + { + this._MinimumDocumentCount = minimumDocumentCount; + return this; + } + + [JsonProperty("order")] + internal IDictionary _Order { get; set; } + + public HistogramAggregationDescriptor OrderAscending(string key) + { + this._Order = new Dictionary { {key, "asc"}}; + return this; + } + + public HistogramAggregationDescriptor OrderDescending(string key) + { + this._Order = new Dictionary { {key, "asc"}}; + return this; + } + + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs b/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs index c5c71793731..4c7b23e3a9d 100644 --- a/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs +++ b/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs @@ -8,28 +8,6 @@ namespace Nest.DSL.Aggregations { - - public class AggregationDescriptor - where T : class - { - private readonly IDictionary _aggregations = - new Dictionary(); - - public AggregationDescriptor Average( - Func, AverageAggregationDescriptor> selector) - { - var agg = selector(new AverageAggregationDescriptor()); - if (agg == null) return this; - this._aggregations.Add("avg", agg); - return this; - } - } - - public interface IAggregationDescriptor - { - - } - public abstract class MetricAggregationBaseDescriptor : IAggregationDescriptor where TMetricAggregation : MetricAggregationBaseDescriptor where T : class @@ -67,19 +45,4 @@ public TMetricAggregation Params(Func, FluentDi return (TMetricAggregation) this; } } - - public abstract class BucketAggregationBaseDescriptor: IAggregationDescriptor - where TBucketAggregation : BucketAggregationBaseDescriptor - where T : class - { - [JsonProperty("aggs")] - internal AggregationDescriptor _Aggregations; - - public TBucketAggregation Aggregations(Func, AggregationDescriptor> selector) - { - this._Aggregations = selector(new AggregationDescriptor()); - return (TBucketAggregation)this; - } - - } } diff --git a/src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs new file mode 100644 index 00000000000..6c5d1f66c24 --- /dev/null +++ b/src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using Elasticsearch.Net; +using Nest.Resolvers; +using Newtonsoft.Json; + +namespace Nest.DSL.Aggregations +{ + public class MissingAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class + { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public MissingAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public MissingAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + } +} \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs index 87178d79ef0..c1e0c45c598 100644 --- a/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs @@ -13,16 +13,4 @@ public class StatsAggregationDescriptor : MetricAggregationBaseDescriptor : MetricAggregationBaseDescriptor, T> - where T : class - { - - } - - public class ValueCountAggregationDescriptor : MetricAggregationBaseDescriptor, T> - where T : class - { - - } } diff --git a/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs index 07f36e9eefb..457b6e3290b 100644 --- a/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs @@ -1,12 +1,47 @@ +using System; using System.Collections.Generic; +using System.Linq.Expressions; using Elasticsearch.Net; +using Nest.Resolvers; using Newtonsoft.Json; namespace Nest.DSL.Aggregations { - public class TermsAggregationDescriptor : MetricAggregationBaseDescriptor, T> + public class TermsAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class { + [JsonProperty("field")] + internal PropertyPathMarker _Field { get; set; } + + public TermsAggregationDescriptor Field(string field) + { + this._Field = field; + return this; + } + + public TermsAggregationDescriptor Field(Expression> field) + { + this._Field = field; + return this; + } + + [JsonProperty("script")] + internal string _Script { get; set; } + + public TermsAggregationDescriptor Script(string script) + { + this._Script = script; + return this; + } + + [JsonProperty("params")] + internal FluentDictionary _Params { get; set; } + + public TermsAggregationDescriptor Params(Func, FluentDictionary> paramSelector) + { + this._Params = paramSelector(new FluentDictionary()); + return this; + } [JsonProperty("size")] internal int? _Size { get; set; } diff --git a/src/Nest/Enums/GeoDistanceType.cs b/src/Nest/Enums/GeoDistanceType.cs new file mode 100644 index 00000000000..4caadcc5515 --- /dev/null +++ b/src/Nest/Enums/GeoDistanceType.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace Nest +{ + [JsonConverter(typeof(StringEnumConverter))] + public enum GeoDistanceType + { + sloppy_arc, + arc, + plane + } +} \ No newline at end of file diff --git a/src/Nest/Enums/GeoHashPrecision.cs b/src/Nest/Enums/GeoHashPrecision.cs new file mode 100644 index 00000000000..2fd9b5d9c16 --- /dev/null +++ b/src/Nest/Enums/GeoHashPrecision.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.Linq.Expressions; + +namespace Nest +{ + public enum GeoHashPrecision + { + /// + /// 5,009.4km x 4,992.6km + /// + precision_1 = 1, + + /// + /// 1,252.3km x 624.1km + /// + precision_2 = 2, + + /// + /// 156.5km x 156km + /// + precision_3 = 3, + + /// + /// 39.1km x 19.5km + /// + precision_4 = 4, + + /// + /// 4.9km x 4.9km + /// + precision_5 = 5, + + /// + /// 1.2km x 609.4m + /// + precision_6 = 6, + + /// + /// 152.9m x 152.4m + /// + precision_7 = 7, + + /// + // 38.2m x 19m + /// + precision_8 = 8, + + /// + /// 4.8m x 4.8m + /// + precision_9 = 9, + + /// + // 1.2m x 59.5cm + /// + precision_10 = 10, + + /// + /// 14.9cm x 14.9cm + /// + precision_11 = 11, + + /// + // 3.7cm x 1.9cm + /// + precision_12 = 12 +} +} diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index f5eb5683c77..b120b7abadb 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -111,15 +111,30 @@ - + + + + + + + + + + + + + + + + From 90c89a5145f3f9212a8e0f8a71453ad495784c16 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 27 Feb 2014 20:29:13 +0100 Subject: [PATCH 3/7] missed missing aggregations, go figure :/ --- src/Nest/DSL/Aggregations/AggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs | 2 +- .../DSL/Aggregations/BucketAggregationBaseDescriptor.cs | 2 +- .../Aggregations/DateHistogramAggregationDescriptor.cs | 2 +- .../DSL/Aggregations/DateRangeAggregationDescriptor.cs | 3 ++- .../Aggregations/ExtendedStatsAggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs | 2 +- .../DSL/Aggregations/GeoDistanceAggregationDescriptor.cs | 4 +++- src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs | 3 ++- src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs | 2 +- .../DSL/Aggregations/HistogramAggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/IAggregationDescriptor.cs | 2 +- .../DSL/Aggregations/Ip4RangeAggregationDescriptor.cs | 8 +++++--- src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs | 2 +- .../DSL/Aggregations/MetricAggregationBaseDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs | 3 ++- src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs | 2 +- src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs | 2 +- .../DSL/Aggregations/ValueCountAggregationDescriptor.cs | 2 +- src/Nest/Nest.csproj | 6 ++++++ 24 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs index 298240e04b3..580035ec9ac 100644 --- a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs @@ -3,7 +3,7 @@ using System.Reflection; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class AggregationDescriptor where T : class diff --git a/src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs index 1b6f14eda62..371e5f4679a 100644 --- a/src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/AverageAggregationDescriptor.cs @@ -6,7 +6,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class AverageAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs index 96a43e6a29c..425a59dfccd 100644 --- a/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs +++ b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs @@ -3,7 +3,7 @@ using System.Linq; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public abstract class BucketAggregationBaseDescriptor: IAggregationDescriptor where TBucketAggregation : BucketAggregationBaseDescriptor diff --git a/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs index ac4babe8d1f..9044230170f 100644 --- a/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs @@ -5,7 +5,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class DateHistogramAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs index 69302e859db..829acaee063 100644 --- a/src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/DateRangeAggregationDescriptor.cs @@ -5,9 +5,10 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class DateRangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class { [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } diff --git a/src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs index 28d4fc1bc10..9f839662714 100644 --- a/src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/ExtendedStatsAggregationDescriptor.cs @@ -1,4 +1,4 @@ -namespace Nest.DSL.Aggregations +namespace Nest { public class ExtendedStatsAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs index 2a84e7b7cc0..81c127316bd 100644 --- a/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class FilterAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs index 94df37dfeb7..827f9a0900f 100644 --- a/src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/GeoDistanceAggregationDescriptor.cs @@ -5,10 +5,12 @@ using System.Linq.Expressions; using Nest.Resolvers; using Newtonsoft.Json; +using Elasticsearch.Net; -namespace Nest.DSL.Aggregations +namespace Nest { public class GeoDistanceAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class { [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } diff --git a/src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs index af08add4a7b..41cebb57ac9 100644 --- a/src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/GeoHashAggregationDescriptor.cs @@ -6,9 +6,10 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class GeoHashAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class { [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } diff --git a/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs index 4c034d07ebb..aeaf70374af 100644 --- a/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class GlobalAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs index 33eb678652b..f3caae900ae 100644 --- a/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs @@ -5,7 +5,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class HistogramAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/IAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/IAggregationDescriptor.cs index feec3faacd7..7a6ddbf3aaa 100644 --- a/src/Nest/DSL/Aggregations/IAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/IAggregationDescriptor.cs @@ -1,4 +1,4 @@ -namespace Nest.DSL.Aggregations +namespace Nest { public interface IAggregationDescriptor { diff --git a/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs index 1ef596c0449..49ca399f023 100644 --- a/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs @@ -5,13 +5,15 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class Ip4RangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class { + [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } - + public Ip4RangeAggregationDescriptor Field(string field) { this._Field = field; @@ -26,7 +28,7 @@ public Ip4RangeAggregationDescriptor Field(Expression> field) [JsonProperty(PropertyName = "ranges")] internal IEnumerable _Ranges { get; set; } - + public Ip4RangeAggregationDescriptor Ranges(params string[] ranges) { var newRanges = from range in ranges let r = new Ip4Range().Mask(range) select r; diff --git a/src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs index b82e3586316..3094431a98d 100644 --- a/src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/MaxAggregationDescriptor.cs @@ -6,7 +6,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class MaxAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs b/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs index 4c7b23e3a9d..864c2c5457e 100644 --- a/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs +++ b/src/Nest/DSL/Aggregations/MetricAggregationBaseDescriptor.cs @@ -6,7 +6,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public abstract class MetricAggregationBaseDescriptor : IAggregationDescriptor where TMetricAggregation : MetricAggregationBaseDescriptor diff --git a/src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs index 197f2624cb6..64a2ce09047 100644 --- a/src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/MinAggregationDescriptor.cs @@ -6,7 +6,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class MinAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs index 6c5d1f66c24..386698e7310 100644 --- a/src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/MissingAggregationDescriptor.cs @@ -5,7 +5,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class MissingAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs index 2f441dde6a5..c5d7356c2bc 100644 --- a/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs @@ -3,7 +3,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class NestedAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs index a87b4b15f93..1a012521e51 100644 --- a/src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/RangeAggregationDescriptor.cs @@ -5,9 +5,10 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class RangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + where T : class { [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } diff --git a/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs index c1e0c45c598..69d1992ce79 100644 --- a/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/StatsAggregationDescriptor.cs @@ -6,7 +6,7 @@ using System.Text.RegularExpressions; using Nest.Resolvers; -namespace Nest.DSL.Aggregations +namespace Nest { public class StatsAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs index 6afb051cc10..6df643fc797 100644 --- a/src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/SumAggregationDescriptor.cs @@ -6,7 +6,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class SumAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs index 457b6e3290b..65c131044b2 100644 --- a/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/TermsAggregationDescriptor.cs @@ -5,7 +5,7 @@ using Nest.Resolvers; using Newtonsoft.Json; -namespace Nest.DSL.Aggregations +namespace Nest { public class TermsAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs index f6e621b8ce7..3519f2a309b 100644 --- a/src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/ValueCountAggregationDescriptor.cs @@ -1,4 +1,4 @@ -namespace Nest.DSL.Aggregations +namespace Nest { public class ValueCountAggregationDescriptor : MetricAggregationBaseDescriptor, T> where T : class diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index b120b7abadb..e9e81f56a05 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -114,6 +114,9 @@ + + + @@ -128,6 +131,7 @@ + @@ -190,6 +194,8 @@ + + From d26f68d3334fc41b20023d324615d6de9d3a1806 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 3 Mar 2014 16:29:23 +0100 Subject: [PATCH 4/7] most of the aggregations responses are mapped and the API is shaping up quite nicely --- .../DSL/Aggregations/AggregationDescriptor.cs | 168 ++++++----- .../BucketAggregationBaseDescriptor.cs | 20 +- .../DateHistogramAggregationDescriptor.cs | 24 +- .../FilterAggregationDescriptor.cs | 13 +- .../Ip4RangeAggregationDescriptor.cs | 8 +- src/Nest/DSL/Facets/Range.cs | 8 + src/Nest/DSL/SearchDescriptor.cs | 14 + .../Domain/Aggregations/AggregationsHelper.cs | 153 ++++++++++ src/Nest/Domain/Aggregations/IAggration.cs | 115 +++++++ src/Nest/Domain/Responses/QueryResponse.cs | 13 + src/Nest/Nest.csproj | 3 + .../Converters/AggregationConverter.cs | 283 ++++++++++++++++++ .../Converters/YesNoBoolConverter.cs | 2 +- src/Nest/Resolvers/ElasticContractResolver.cs | 3 + .../Aggregations/ParseResponseItemsTests.cs | 255 ++++++++++++++++ .../Aggregations/TermsAggregationTests.cs | 85 ++++++ .../Nest.Tests.Integration.csproj | 2 + .../DataSources/IpSource.cs | 26 ++ .../Domain/ElasticsearchProject.cs | 1 + .../Nest.Tests.MockData.csproj | 1 + src/Tests/Nest.Tests.MockData/NestTestData.cs | 1 + 21 files changed, 1104 insertions(+), 94 deletions(-) create mode 100644 src/Nest/Domain/Aggregations/AggregationsHelper.cs create mode 100644 src/Nest/Domain/Aggregations/IAggration.cs create mode 100644 src/Nest/Resolvers/Converters/AggregationConverter.cs create mode 100644 src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs create mode 100644 src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs create mode 100644 src/Tests/Nest.Tests.MockData/DataSources/IpSource.cs diff --git a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs index 580035ec9ac..fbaba79612b 100644 --- a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using Elasticsearch.Net; using Newtonsoft.Json; namespace Nest @@ -8,169 +9,178 @@ namespace Nest public class AggregationDescriptor where T : class { - private readonly IDictionary _aggregations = - new Dictionary(); + internal readonly IDictionary> _Aggregations = + new Dictionary>(); - public AverageAggregationDescriptor _Average { get; set; } - public AggregationDescriptor Average(Func, AverageAggregationDescriptor> selector) + [JsonProperty("aggs", Order = 100)] + [JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))] + internal IDictionary> _NestedAggregations; + + + [JsonProperty("avg")] + internal AverageAggregationDescriptor _Average { get; set; } + public AggregationDescriptor Average(string name, Func, AverageAggregationDescriptor> selector) { - this._Average = selector(new AverageAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Average = d); } [JsonProperty("date_histogram")] - public DateHistogramAggregationDescriptor _DateHistogram { get; set; } - public AggregationDescriptor DateHistogram( + internal DateHistogramAggregationDescriptor _DateHistogram { get; set; } + public AggregationDescriptor DateHistogram(string name, Func, DateHistogramAggregationDescriptor> selector) { - this._DateHistogram = selector(new DateHistogramAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._DateHistogram = d); } [JsonProperty("date_range")] - public DateRangeAggregationDescriptor _DateRange { get; set; } - public AggregationDescriptor DateRange( + internal DateRangeAggregationDescriptor _DateRange { get; set; } + public AggregationDescriptor DateRange(string name, Func, DateRangeAggregationDescriptor> selector) { - this._DateRange = selector(new DateRangeAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._DateRange = d); } [JsonProperty("extended_stats")] - public ExtendedStatsAggregationDescriptor _ExtendedStats { get; set; } - public AggregationDescriptor ExtendedStats( + internal ExtendedStatsAggregationDescriptor _ExtendedStats { get; set; } + public AggregationDescriptor ExtendedStats(string name, Func, ExtendedStatsAggregationDescriptor> selector) { - this._ExtendedStats = selector(new ExtendedStatsAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._ExtendedStats = d); } [JsonProperty("filter")] - public FilterAggregationDescriptor _Filter { get; set; } - public AggregationDescriptor Filter( + internal FilterAggregationDescriptor _Filter { get; set; } + public AggregationDescriptor Filter(string name, Func, FilterAggregationDescriptor> selector) { - this._Filter = selector(new FilterAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Filter = d); } [JsonProperty("geo_distance")] - public GeoDistanceAggregationDescriptor _GeoDistance { get; set; } - public AggregationDescriptor GeoDistance( + internal GeoDistanceAggregationDescriptor _GeoDistance { get; set; } + public AggregationDescriptor GeoDistance(string name, Func, GeoDistanceAggregationDescriptor> selector) { - this._GeoDistance = selector(new GeoDistanceAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._GeoDistance = d); } [JsonProperty("geo_hash")] - public GeoHashAggregationDescriptor _GeoHash { get; set; } - public AggregationDescriptor GeoHash( + internal GeoHashAggregationDescriptor _GeoHash { get; set; } + public AggregationDescriptor GeoHash(string name, Func, GeoHashAggregationDescriptor> selector) { - this._GeoHash = selector(new GeoHashAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._GeoHash = d); } [JsonProperty("histogram")] - public HistogramAggregationDescriptor _Histogram { get; set; } - public AggregationDescriptor Histogram( + internal HistogramAggregationDescriptor _Histogram { get; set; } + public AggregationDescriptor Histogram(string name, Func, HistogramAggregationDescriptor> selector) { - this._Histogram = selector(new HistogramAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Histogram = d); } [JsonProperty("global")] - public GlobalAggregationDescriptor _Global { get; set; } - public AggregationDescriptor Global( + internal GlobalAggregationDescriptor _Global { get; set; } + public AggregationDescriptor Global(string name, Func, GlobalAggregationDescriptor> selector) { - this._Global = selector(new GlobalAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Global = d); } - [JsonProperty("ip4_range")] - public Ip4RangeAggregationDescriptor _Ip4Range { get; set; } - public AggregationDescriptor Ip4Range( - Func, Ip4RangeAggregationDescriptor> selector) + [JsonProperty("ip_range")] + internal IpRangeAggregationDescriptor _IpRange { get; set; } + public AggregationDescriptor IpRange(string name, + Func, IpRangeAggregationDescriptor> selector) { - this._Ip4Range = selector(new Ip4RangeAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._IpRange = d); } [JsonProperty("max")] - public MaxAggregationDescriptor _Max { get; set; } - public AggregationDescriptor Max(Func, MaxAggregationDescriptor> selector) + internal MaxAggregationDescriptor _Max { get; set; } + public AggregationDescriptor Max(string name, Func, MaxAggregationDescriptor> selector) { - this._Max = selector(new MaxAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Max = d); } [JsonProperty("min")] - public MinAggregationDescriptor _Min { get; set; } - public AggregationDescriptor Min(Func, MinAggregationDescriptor> selector) + internal MinAggregationDescriptor _Min { get; set; } + public AggregationDescriptor Min(string name, Func, MinAggregationDescriptor> selector) { - this._Min = selector(new MinAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Min = d); } [JsonProperty("missing")] - public MissingAggregationDescriptor _Missing { get; set; } - public AggregationDescriptor Missing(Func, MissingAggregationDescriptor> selector) + internal MissingAggregationDescriptor _Missing { get; set; } + public AggregationDescriptor Missing(string name, Func, MissingAggregationDescriptor> selector) { - this._Missing = selector(new MissingAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Missing = d); } [JsonProperty("nested")] - public NestedAggregationDescriptor _Nested { get; set; } - public AggregationDescriptor Nested(Func, NestedAggregationDescriptor> selector) + internal NestedAggregationDescriptor _Nested { get; set; } + public AggregationDescriptor Nested(string name, Func, NestedAggregationDescriptor> selector) { - this._Nested = selector(new NestedAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Nested = d); } [JsonProperty("range")] - public RangeAggregationDescriptor _Range { get; set; } - public AggregationDescriptor Range(Func, RangeAggregationDescriptor> selector) + internal RangeAggregationDescriptor _Range { get; set; } + public AggregationDescriptor Range(string name, Func, RangeAggregationDescriptor> selector) { - this._Range = selector(new RangeAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Range = d); } [JsonProperty("stats")] - public StatsAggregationDescriptor _Stats { get; set; } - public AggregationDescriptor Stats(Func, StatsAggregationDescriptor> selector) + internal StatsAggregationDescriptor _Stats { get; set; } + public AggregationDescriptor Stats(string name, Func, StatsAggregationDescriptor> selector) { - this._Stats = selector(new StatsAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Stats = d); } [JsonProperty("sum")] - public SumAggregationDescriptor _Sum { get; set; } - public AggregationDescriptor Sum(Func, SumAggregationDescriptor> selector) + internal SumAggregationDescriptor _Sum { get; set; } + public AggregationDescriptor Sum(string name, Func, SumAggregationDescriptor> selector) { - this._Sum = selector(new SumAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Sum = d); } [JsonProperty("terms")] - public TermsAggregationDescriptor _Terms { get; set; } - public AggregationDescriptor Terms(Func, TermsAggregationDescriptor> selector) + internal TermsAggregationDescriptor _Terms { get; set; } + public AggregationDescriptor Terms(string name, Func, TermsAggregationDescriptor> selector) { - this._Terms = selector(new TermsAggregationDescriptor()); - return this; + return _SetInnerAggregation(name, selector, (a, d) => a._Terms = d); } [JsonProperty("value_count")] - public ValueCountAggregationDescriptor _ValueCount { get; set; } - public AggregationDescriptor ValueCount( + internal ValueCountAggregationDescriptor _ValueCount { get; set; } + public AggregationDescriptor ValueCount(string name, Func, ValueCountAggregationDescriptor> selector) { - this._ValueCount = selector(new ValueCountAggregationDescriptor()); + return _SetInnerAggregation(name, selector, (a, d) => a._ValueCount = d); + } + + private AggregationDescriptor _SetInnerAggregation( + string key, + Func selector + , Action, TAggregation> setter + ) + where TAggregation : IAggregationDescriptor, new() + + { + var innerDescriptor = selector(new TAggregation()); + var descriptor = new AggregationDescriptor(); + setter(descriptor, innerDescriptor); + var bucket = innerDescriptor as IBucketAggregationDescriptor; + if (bucket != null && bucket.NestedAggregations.HasAny()) + { + descriptor._NestedAggregations = bucket.NestedAggregations; + } + this._Aggregations[key] = descriptor; return this; + } + } } \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs index 425a59dfccd..21775117f94 100644 --- a/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs +++ b/src/Nest/DSL/Aggregations/BucketAggregationBaseDescriptor.cs @@ -5,16 +5,26 @@ namespace Nest { - public abstract class BucketAggregationBaseDescriptor: IAggregationDescriptor + + public interface IBucketAggregationDescriptor + where T : class + { + + IDictionary> NestedAggregations { get; set; } + } + + public abstract class BucketAggregationBaseDescriptor + : IAggregationDescriptor, IBucketAggregationDescriptor where TBucketAggregation : BucketAggregationBaseDescriptor where T : class { - [JsonProperty("aggs")] - internal AggregationDescriptor _Aggregations; + IDictionary> IBucketAggregationDescriptor.NestedAggregations { get; set; } public TBucketAggregation Aggregations(Func, AggregationDescriptor> selector) - { - this._Aggregations = selector(new AggregationDescriptor()); + { + var aggs = selector(new AggregationDescriptor()); + if (aggs == null) return (TBucketAggregation)this; + ((IBucketAggregationDescriptor)this).NestedAggregations = aggs._Aggregations; return (TBucketAggregation)this; } } diff --git a/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs index 9044230170f..d6f28c88f8d 100644 --- a/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/DateHistogramAggregationDescriptor.cs @@ -3,16 +3,23 @@ using System.Linq.Expressions; using Elasticsearch.Net; using Nest.Resolvers; +using Nest.Resolvers.Converters; using Newtonsoft.Json; namespace Nest { - public class DateHistogramAggregationDescriptor : MetricAggregationBaseDescriptor, T> + public class DateHistogramAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class { [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } - + + public DateHistogramAggregationDescriptor() + { + this.Format("yyyy-MM-dd"); + } + + public DateHistogramAggregationDescriptor Field(string field) { this._Field = field; @@ -51,7 +58,18 @@ public DateHistogramAggregationDescriptor Interval(string interval) this._Interval = interval; return this; } - + + [JsonProperty("format")] + internal string _Format { get; set; } + + public DateHistogramAggregationDescriptor Format(string format) + { + if (format.IsNullOrEmpty()) + return this; + this._Format = format; + return this; + } + [JsonProperty("min_doc_count")] internal int? _MinimumDocumentCount { get; set; } diff --git a/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs index 81c127316bd..85d8224c4c7 100644 --- a/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/FilterAggregationDescriptor.cs @@ -1,12 +1,15 @@ using System; +using Nest.Resolvers.Converters; using Newtonsoft.Json; namespace Nest { - public class FilterAggregationDescriptor : BucketAggregationBaseDescriptor, T> + [JsonConverter(typeof(CustomJsonConverter))] + public class FilterAggregationDescriptor + : BucketAggregationBaseDescriptor, T> + , ICustomJson where T : class { - [JsonProperty("filter")] internal BaseFilter _Filter { get; set; } public FilterAggregationDescriptor Filter(Func, BaseFilter> selector) @@ -14,5 +17,11 @@ public FilterAggregationDescriptor Filter(Func, BaseFilte this._Filter = selector(new FilterDescriptor()); return this; } + + + object ICustomJson.GetCustomJson() + { + return _Filter; + } } } \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs index 49ca399f023..65605d46006 100644 --- a/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs @@ -7,20 +7,20 @@ namespace Nest { - public class Ip4RangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + public class IpRangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class { [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } - public Ip4RangeAggregationDescriptor Field(string field) + public IpRangeAggregationDescriptor Field(string field) { this._Field = field; return this; } - public Ip4RangeAggregationDescriptor Field(Expression> field) + public IpRangeAggregationDescriptor Field(Expression> field) { this._Field = field; return this; @@ -29,7 +29,7 @@ public Ip4RangeAggregationDescriptor Field(Expression> field) [JsonProperty(PropertyName = "ranges")] internal IEnumerable _Ranges { get; set; } - public Ip4RangeAggregationDescriptor Ranges(params string[] ranges) + public IpRangeAggregationDescriptor Ranges(params string[] ranges) { var newRanges = from range in ranges let r = new Ip4Range().Mask(range) select r; this._Ranges = newRanges; diff --git a/src/Nest/DSL/Facets/Range.cs b/src/Nest/DSL/Facets/Range.cs index bdb03411f8c..f12ae741966 100644 --- a/src/Nest/DSL/Facets/Range.cs +++ b/src/Nest/DSL/Facets/Range.cs @@ -14,7 +14,15 @@ public class Range where T : struct [JsonProperty(PropertyName = "to")] internal T? _To { get; set; } + + [JsonProperty(PropertyName = "key")] + internal string _Key { get; set; } + public Range Key(string key) + { + this._Key = key; + return this; + } public Range From(T value) { this._From = value; diff --git a/src/Nest/DSL/SearchDescriptor.cs b/src/Nest/DSL/SearchDescriptor.cs index ab12b7d1813..82cdf46ee66 100644 --- a/src/Nest/DSL/SearchDescriptor.cs +++ b/src/Nest/DSL/SearchDescriptor.cs @@ -285,6 +285,20 @@ internal RawOrFilterDescriptor _FilterOrRaw [JsonProperty(PropertyName = "_source")] internal object _Source { get; set; } + + [JsonProperty(PropertyName = "aggs")] + [JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))] + internal IDictionary> _Aggregations { get; set; } + + public SearchDescriptor Aggregations(Func, AggregationDescriptor> aggregationsSelector) + { + var aggs = aggregationsSelector(new AggregationDescriptor()); + if (aggs == null) return this; + this._Aggregations = aggs._Aggregations; + return this; + } + + public SearchDescriptor Source(bool include = true) { this._Source = include; diff --git a/src/Nest/Domain/Aggregations/AggregationsHelper.cs b/src/Nest/Domain/Aggregations/AggregationsHelper.cs new file mode 100644 index 00000000000..6fc5822b3ec --- /dev/null +++ b/src/Nest/Domain/Aggregations/AggregationsHelper.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Nest +{ + public class AggregationsHelper + { + public IDictionary Aggregations { get; internal protected set; } + + public AggregationsHelper() + { + + } + + public AggregationsHelper(IDictionary aggregations) + { + this.Aggregations = aggregations; + } + + private TAggregation TryGet(string key) + where TAggregation : class, IAggregation + { + IAggregation agg; + if (this.Aggregations.TryGetValue(key, out agg)) + return agg as TAggregation; + return null; + + } + + public ValueMetric Min(string key) + { + return this.TryGet(key); + } + + public ValueMetric Max(string key) + { + return this.TryGet(key); + } + + public ValueMetric Sum(string key) + { + return this.TryGet(key); + } + + public ValueMetric Average(string key) + { + return this.TryGet(key); + } + + public ValueMetric ValueCount(string key) + { + return this.TryGet(key); + } + + public StatsMetric Stats(string key) + { + return this.TryGet(key); + } + + public ExtendedStatsMetric ExtendedStats(string key) + { + return this.TryGet(key); + } + + public SingleBucket Global(string key) + { + return this.TryGet(key); + } + + public SingleBucket Filter(string key) + { + return this.TryGet(key); + } + + public SingleBucket Missing(string key) + { + return this.TryGet(key); + } + + public NestedBucket Nested(string key) + { + return this.TryGet(key); + } + + public Bucket Terms(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + public Bucket Histogram(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + public Bucket GeoHash(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + public Bucket Range(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + public Bucket DateRange(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + public Bucket IpRange(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + public Bucket GeoDistance(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + public Bucket DateHistogram(string key) + { + var bucket = this.TryGet(key); + var b = new Bucket(); + b.Items = bucket.Items.OfType().ToList(); + return b; + } + + + + + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/IAggration.cs b/src/Nest/Domain/Aggregations/IAggration.cs new file mode 100644 index 00000000000..72946815d55 --- /dev/null +++ b/src/Nest/Domain/Aggregations/IAggration.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Nest +{ + public interface IAggregation + { + } + + public interface IMetricAggregation : IAggregation + { + } + + public interface IBucketAggregation : IAggregation + { + IDictionary Aggregations { get; } + //AggregationsHelper Aggs { get; } + } + public abstract class BucketAggregationBase : AggregationsHelper , IBucketAggregation + { + //public IDictionary Aggregations { get; internal protected set; } + //private AggregationsHelper _agg = null; + + //public AggregationsHelper Aggs + //{ + // get { return _agg ?? (_agg = new AggregationsHelper(this.Aggregations)); } + //} + } + + public class ValueMetric : IMetricAggregation + { + public double Value { get; set; } + } + + public class StatsMetric : IMetricAggregation + { + public long Count { get; set; } + public double Min { get; set; } + public double Max { get; set; } + public double Average { get; set; } + public double Sum { get; set; } + } + + public class ExtendedStatsMetric : IMetricAggregation + { + public long Count { get; set; } + public double Min { get; set; } + public double Max { get; set; } + public double Average { get; set; } + public double Sum { get; set; } + public double SumOfSquares { get; set; } + public double Variance { get; set; } + public double StdDeviation { get; set; } + } + + + public class SingleBucket : BucketAggregationBase + { + public long DocCount { get; set; } + } + + public class NestedBucket : BucketAggregationBase + { + } + + public class Bucket : BucketAggregationBase + where TBucketItem : IBucketItem + { + public IList Items { get; set; } + } + + public class Bucket : IAggregation + { + public IEnumerable Items { get; set; } + } + + public interface IBucketItem : IAggregation + { + } + + public class KeyItem : BucketAggregationBase, IBucketItem + { + public string Key { get; set; } + public long DocCount { get; set; } + } + + public class DateHistogramItem : BucketAggregationBase, IBucketItem + { + public long Key { get; set; } + public string KeyAsString { get; set; } + + public DateTime Date + { + get + { + return new DateTime(1970, 1, 1).AddMilliseconds(0 + this.Key); + } + } + + public long DocCount { get; set; } + } + + public class RangeItem : BucketAggregationBase, IBucketItem + { + public string Key { get; set; } + public double? From { get; set; } + public string FromAsString { get; set; } + public double? To { get; set; } + public string ToAsString { get; set; } + public long DocCount { get; set; } + } + +} diff --git a/src/Nest/Domain/Responses/QueryResponse.cs b/src/Nest/Domain/Responses/QueryResponse.cs index 40be931d3bd..4322f82c46d 100644 --- a/src/Nest/Domain/Responses/QueryResponse.cs +++ b/src/Nest/Domain/Responses/QueryResponse.cs @@ -13,6 +13,8 @@ public interface IQueryResponse : IResponse where T : class ShardsMetaData Shards { get; } HitsMetaData HitsMetaData { get; } IDictionary Facets { get; } + IDictionary Aggregations { get; } + AggregationsHelper Aggs { get; } IDictionary Suggest { get; } int ElapsedMilliseconds { get; } string ScrollId { get; } @@ -44,7 +46,18 @@ public QueryResponse() [JsonProperty(PropertyName = "facets")] [JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))] public IDictionary Facets { get; internal set; } + + [JsonProperty(PropertyName = "aggregations")] + [JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))] + public IDictionary Aggregations { get; internal set; } + + private AggregationsHelper _agg = null; + public AggregationsHelper Aggs + { + get { return _agg ?? (_agg = new AggregationsHelper(this.Aggregations)); } + } + [JsonProperty(PropertyName = "suggest")] public IDictionary Suggest { get; internal set; } diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index e9e81f56a05..34b5141b817 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -93,6 +93,8 @@ + + @@ -630,6 +632,7 @@ + diff --git a/src/Nest/Resolvers/Converters/AggregationConverter.cs b/src/Nest/Resolvers/Converters/AggregationConverter.cs new file mode 100644 index 00000000000..b7dec751b39 --- /dev/null +++ b/src/Nest/Resolvers/Converters/AggregationConverter.cs @@ -0,0 +1,283 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using Elasticsearch.Net; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Nest.Resolvers.Converters +{ + + public class AggregationConverter : JsonConverter + { + public override bool CanWrite + { + get { return false; } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotSupportedException(); + } + + private IAggregation ReadAggregation(JsonReader reader, JsonSerializer serializer) + { + if (reader.TokenType != JsonToken.StartObject) + return null; + reader.Read(); + + if (reader.TokenType != JsonToken.PropertyName) + return null; + + var property = reader.Value as string; + switch (property) + { + case "value": + return GetValueMetricOrAggregation(reader, serializer); + case "buckets": + return GetBucketAggregation(reader, serializer); + case "key": + return GetKeyedBucketItem(reader, serializer); + case "from": + case "to": + return GetRangeAggregation(reader, serializer); + case "key_as_string": + return GetDateHistogramAggregation(reader, serializer); + case "count": + return GetStatsAggregation(reader, serializer); + case "doc_count": + return GetSingleBucketAggregation(reader, serializer); + default: + return null; //TODO assume nested + + } + } + + private IAggregation GetSingleBucketAggregation(JsonReader reader, JsonSerializer serializer) + { + reader.Read(); + var docCount = (reader.Value as long?).GetValueOrDefault(0); + var bucket = new SingleBucket() {DocCount = docCount}; + reader.Read(); + bucket.Aggregations = this.GetNestedAggregations(reader, serializer); + + return bucket; + } + + + private IAggregation GetStatsAggregation(JsonReader reader, JsonSerializer serializer) + { + reader.Read(); + var count = (reader.Value as long?).GetValueOrDefault(0); + reader.Read(); reader.Read(); + var min = (reader.Value as double?).GetValueOrDefault(0); + reader.Read(); reader.Read(); + var max = (reader.Value as double?).GetValueOrDefault(0); + reader.Read(); reader.Read(); + var average = (reader.Value as double?).GetValueOrDefault(0); + reader.Read(); reader.Read(); + var sum = (reader.Value as double?).GetValueOrDefault(0); + + reader.Read(); + if (reader.TokenType == JsonToken.EndObject) + return new StatsMetric() + { + Average = average, + Count = count, + Max = max, + Min = min, + Sum = sum + }; + + reader.Read(); + var sumOfSquares = (reader.Value as double?).GetValueOrDefault(0); + reader.Read(); reader.Read(); + var variance = (reader.Value as double?).GetValueOrDefault(0); + reader.Read(); reader.Read(); + var stdVariation = (reader.Value as double?).GetValueOrDefault(0); + reader.Read(); + return new ExtendedStatsMetric() + { + Average = average, + Count = count, + Max = max, + Min = min, + StdDeviation = stdVariation, + Sum = sum, + SumOfSquares = sumOfSquares, + Variance = variance + }; + } + + private IAggregation GetDateHistogramAggregation(JsonReader reader, JsonSerializer serializer) + { + reader.Read(); + var keyAsString = reader.Value as string; + reader.Read(); reader.Read(); + var key = (reader.Value as long?).GetValueOrDefault(0); + reader.Read(); reader.Read(); + var docCount = (reader.Value as long?).GetValueOrDefault(0); + reader.Read(); + + var dateHistogram = new DateHistogramItem() {Key = key, KeyAsString = keyAsString, DocCount = docCount}; + dateHistogram.Aggregations = this.GetNestedAggregations(reader, serializer); + return dateHistogram; + + } + + public IAggregation GetRangeAggregation(JsonReader reader, JsonSerializer serializer, string key = null) + { + string fromAsString = null, toAsString = null; + long? docCount = null; + double? toDouble = null, fromDouble = null; + + var readExpectedProperty = true; + while (readExpectedProperty) + { + switch (reader.Value as string) + { + case "from": + reader.Read(); + if (reader.ValueType == typeof (double)) + fromDouble = (double) reader.Value; + reader.Read(); + break; + case "to": + reader.Read(); + if (reader.ValueType == typeof (double)) + toDouble = (double) reader.Value; + reader.Read(); + break; + case "key": + reader.Read(); + key = reader.Value as string; + reader.Read(); + break; + case "from_as_string": + reader.Read(); + fromAsString = reader.Value as string; + reader.Read(); + break; + case "to_as_string": + reader.Read(); + toAsString = reader.Value as string; + reader.Read(); + break; + case "doc_count": + reader.Read(); + docCount = (reader.Value as long?).GetValueOrDefault(0); + reader.Read(); + break; + default: + readExpectedProperty = false; + break; + } + } + var bucket = new RangeItem + { + Key = key, + From = fromDouble, + To = toDouble, + DocCount = docCount.GetValueOrDefault(), + FromAsString = fromAsString, + ToAsString = toAsString + }; + + bucket.Aggregations = this.GetNestedAggregations(reader, serializer); + return bucket; + + } + + private IAggregation GetKeyedBucketItem(JsonReader reader, JsonSerializer serializer) + { + reader.Read(); + var key = reader.Value as string; + reader.Read(); + var property = reader.Value as string; + if (property == "from" || property == "to") + return GetRangeAggregation(reader, serializer, key); + + + var keyItem = new KeyItem(); + keyItem.Key = key; + reader.Read(); //doc_count; + var docCount = reader.Value as long?; + keyItem.DocCount = docCount.GetValueOrDefault(0); + reader.Read(); + keyItem.Aggregations = this.GetNestedAggregations(reader, serializer); + return keyItem; + + } + + private IDictionary GetNestedAggregations(JsonReader reader, JsonSerializer serializer) + { + if (reader.TokenType != JsonToken.PropertyName) + return null; + + var nestedAggs = new Dictionary(); + var currentDepth = reader.Depth; + do + { + var propertyName = reader.Value as string; + reader.Read(); + var agg = this.ReadAggregation(reader, serializer); + nestedAggs.Add(propertyName, agg); + reader.Read(); + if (reader.Depth == currentDepth && reader.TokenType == JsonToken.EndObject || reader.Depth < currentDepth) + break; + } while (true); + return nestedAggs; + } + + private IAggregation GetBucketAggregation(JsonReader reader, JsonSerializer serializer) + { + var bucket = new Bucket(); + var aggregations = new List(); + reader.Read(); + if (reader.TokenType != JsonToken.StartArray) + return null; + var currentDepth = reader.Depth; + reader.Read(); //move from start array to start object + if (reader.TokenType == JsonToken.EndArray) + { + reader.Read(); + bucket.Items = Enumerable.Empty(); + return bucket; + } + do + { + + var agg = this.ReadAggregation(reader, serializer); + aggregations.Add(agg); + reader.Read(); + } while (reader.TokenType != JsonToken.EndArray);// && reader.Depth != currentDepth); + bucket.Items = aggregations; + reader.Read(); + return bucket; + } + + + private IAggregation GetValueMetricOrAggregation(JsonReader reader, JsonSerializer serializer) + { + reader.Read(); + //if (reader.TokenType = JsonToken.StartObject) + var metric = new ValueMetric() {Value = (reader.Value as double?).GetValueOrDefault(0)}; + reader.Read(); + //todo value is a nested aggregation recurse. + return metric; + } + + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return this.ReadAggregation(reader, serializer); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(IAggregation); + } + } +} \ No newline at end of file diff --git a/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs b/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs index 4e517f70575..a790f6b5708 100644 --- a/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs +++ b/src/Nest/Resolvers/Converters/YesNoBoolConverter.cs @@ -19,7 +19,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var v = reader.Value.ToString(); - return reader.Value != null && (v == "yes" || v == " True"); + return reader.Value != null && (v == "yes" || v == "True"); } public override bool CanConvert(Type objectType) diff --git a/src/Nest/Resolvers/ElasticContractResolver.cs b/src/Nest/Resolvers/ElasticContractResolver.cs index 8008be348c9..97140c03c64 100644 --- a/src/Nest/Resolvers/ElasticContractResolver.cs +++ b/src/Nest/Resolvers/ElasticContractResolver.cs @@ -52,6 +52,9 @@ protected override JsonContract CreateContract(Type objectType) if (objectType == typeof(Facet)) contract.Converter = new FacetConverter(); + if (objectType == typeof(IAggregation)) + contract.Converter = new AggregationConverter(); + if (objectType == typeof(DateTime) || objectType == typeof(DateTime?)) contract.Converter = new IsoDateTimeConverter(); diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs new file mode 100644 index 00000000000..afad2c5a181 --- /dev/null +++ b/src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs @@ -0,0 +1,255 @@ +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest.Tests.MockData.Domain; +using NUnit.Framework; + +namespace Nest.Tests.Integration.Aggregations +{ + /// + /// Tests that test whether the query response can be successfully mapped or not + /// + [TestFixture] + public class ParseResponseItemsTests : IntegrationTests + { + [Test] + public void KeyItem() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Terms("my_terms_agg", t=>t + .Field(p=>p.Country) + .Aggregations(ta=>ta + .Average("averge", avg=>avg + .Field(p=>p.LOC) + ) + ) + ) + + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as Bucket; + firstAgg.Items.Should().HaveCount(10); + + //request.Should().Contain("averge"); + } + + [Test] + public void ValueMetric() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Average("my_avg", avg=>avg + .Field(p=>p.LOC) + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as ValueMetric; + firstAgg.Should().NotBeNull(); + firstAgg.Value.Should().BeGreaterThan(1); + } + + [Test] + public void SingleBucket() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Filter("my_filtered_agg", ff=>ff + .Filter(f=>!f.Term(p=>p.Name, "nest")) + .Aggregations(aa=>aa + .Terms("my_terms", ta=>ta + .Field(p=>p.Name) + ) + ) + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as SingleBucket; + firstAgg.Should().NotBeNull(); + firstAgg.DocCount.Should().BeGreaterThan(1); + firstAgg.Aggregations.Should().NotBeEmpty(); + } + + [Test] + public void DateHistogramItem() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .DateHistogram("my_dateh", dh=>dh + .Field(p=>p.StartedOn) + .Interval("1d") + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as Bucket; + firstAgg.Should().NotBeNull(); + firstAgg.Items.Should().NotBeEmpty(); + var grams = firstAgg.Items.OfType(); + grams.Should().NotBeEmpty(); + } + + [Test] + public void GeoDistanceItem() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .GeoDistance("my_geod", dh=>dh + .Field(p=>p.Origin) + //.DistanceType(GeoDistanceType.sloppy_arc) + .Origin(28.0, 28.0) + .Unit(GeoUnit.km) + .Ranges( + r=>r.To(1), + r=>r.From(1).To(100) + ) + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as Bucket; + firstAgg.Should().NotBeNull(); + firstAgg.Items.Should().NotBeEmpty(); + var grams = firstAgg.Items.OfType(); + grams.Should().NotBeEmpty(); + } + + [Test] + public void RangeItem() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Range("my_geod", dh=>dh + .Field(p=>p.LongValue) + //.DistanceType(GeoDistanceType.sloppy_arc) + .Ranges( + r=>r.Key("small_longs").To(1), + r=>r.From(1).To(100) + ) + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as Bucket; + firstAgg.Should().NotBeNull(); + firstAgg.Items.Should().NotBeEmpty(); + var grams = firstAgg.Items.OfType(); + grams.Should().NotBeEmpty(); + } + + [Test] + public void DateRangeItem() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .DateRange("my_geod", dh=>dh + .Field(p=>p.StartedOn) + .Ranges( + r=>r.To("now-10M/M"), + r=>r.From("now-10M/M") + ) + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as Bucket; + firstAgg.Should().NotBeNull(); + firstAgg.Items.Should().NotBeEmpty(); + var grams = firstAgg.Items.OfType(); + grams.Should().NotBeEmpty(); + } + [Test] + public void IpRangeItem() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .IpRange("my_ip", dh=>dh + .Field(p=>p.PingIP) + .Ranges("10.0.0.0/25") + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as Bucket; + firstAgg.Should().NotBeNull(); + firstAgg.Items.Should().NotBeEmpty(); + var grams = firstAgg.Items.OfType(); + grams.Should().NotBeEmpty(); + } + [Test] + public void StatsMetric() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Stats("my_stats", avg=>avg + .Field(p=>p.LongValue) + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as StatsMetric; + firstAgg.Should().NotBeNull(); + firstAgg.Count.Should().BeGreaterThan(1); + firstAgg.Min.Should().NotBe(0); + firstAgg.Max.Should().NotBe(0); + firstAgg.Average.Should().NotBe(0); + firstAgg.Sum.Should().BeGreaterThan(1); + } + + [Test] + public void ExtendedStatsMetric() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .ExtendedStats("my_stats", avg=>avg + .Field(p=>p.LongValue) + ) + ) + ); + var request = results.ConnectionStatus.Request.Utf8String(); + results.IsValid.Should().BeTrue("{0}", request); + results.Aggregations.Should().HaveCount(1); + var firstAgg = results.Aggregations.First().Value as ExtendedStatsMetric; + firstAgg.Should().NotBeNull(); + firstAgg.Count.Should().BeGreaterThan(1); + firstAgg.Min.Should().NotBe(0); + firstAgg.Max.Should().NotBe(0); + firstAgg.Average.Should().NotBe(0); + firstAgg.Sum.Should().BeGreaterThan(1); + firstAgg.SumOfSquares.Should().NotBe(0); + firstAgg.Variance.Should().NotBe(0); + firstAgg.StdDeviation.Should().NotBe(0); + } + } +} \ No newline at end of file diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs new file mode 100644 index 00000000000..d3f55f193df --- /dev/null +++ b/src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs @@ -0,0 +1,85 @@ +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest.Tests.MockData.Domain; +using NUnit.Framework; + +namespace Nest.Tests.Integration.Aggregations +{ + [TestFixture] + public class TermsAggregationTests : IntegrationTests + { + [Test] + public void WrongFieldName() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Terms("my_terms_agg", t=>t + .Field("this_field_name_does_not_exist") + ) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Terms("my_terms_agg"); + termBucket.Should().NotBeNull(); + termBucket.Items.Should().BeEmpty(); + } + + [Test] + public void ExistingFieldName() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Terms("my_terms_agg", t=>t + .Field(p=>p.Name) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Terms("my_terms_agg"); + termBucket.Should().NotBeNull(); + termBucket.Items.Should().NotBeEmpty() + .And.OnlyContain(i=>!i.Key.IsNullOrEmpty()) + .And.OnlyContain(i=>i.DocCount > 0); + } + + [Test] + public void NestedEmptyAggregation() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Terms("countries", t=>t + .Field(p=>p.Country) + .Aggregations(aa=>aa + .Terms("noop", tt => tt.Field("noop")) + .Terms("names", tt => tt.Field(p=>p.Name)) + ) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Terms("countries"); + termBucket.Should().NotBeNull(); + termBucket.Items.Should().NotBeEmpty() + .And.OnlyContain(i => !i.Key.IsNullOrEmpty()) + .And.OnlyContain(i => i.DocCount > 0); + + foreach (var term in termBucket.Items) + { + var country = term.Key; + country.Should().NotBeBlank(); + + var noop = term.Terms("noop"); + noop.Should().NotBeNull(); + noop.Items.Should().BeEmpty(); + + var names = term.Terms("names"); + names.Should().NotBeNull(); + names.Items.Should().NotBeEmpty(); + } + } + } +} \ No newline at end of file diff --git a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj index 53103a8eced..f60651d5db3 100644 --- a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj +++ b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj @@ -68,6 +68,8 @@ + + diff --git a/src/Tests/Nest.Tests.MockData/DataSources/IpSource.cs b/src/Tests/Nest.Tests.MockData/DataSources/IpSource.cs new file mode 100644 index 00000000000..772466aa029 --- /dev/null +++ b/src/Tests/Nest.Tests.MockData/DataSources/IpSource.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using AutoPoco.Engine; + +namespace Nest.Tests.MockData.DataSources +{ + public class IpSource : DatasourceBase + { + private static readonly Random _random = new Random(); + + private static readonly string[] _ips = new[]{ + "127.0.0.1", + "10.0.0.1", + "10.0.0.2", + "192.168.0.1" + }; + + public override string Next(IGenerationSession session) + { + string ip = _ips[_random.Next(0, _ips.Length)]; + return ip; + } + } +} diff --git a/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs b/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs index 3ae9e483adc..3aa3099e4fc 100644 --- a/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs +++ b/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs @@ -28,6 +28,7 @@ public class ElasticsearchProject public GeoLocation Origin { get; set; } public DateTime StartedOn { get; set; } + [ElasticProperty(Type=FieldType.ip)] public string PingIP { get; set; } public GeoShape MyGeoShape { get; set; } diff --git a/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj b/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj index 02cdde12775..d0b795eb98e 100644 --- a/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj +++ b/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj @@ -81,6 +81,7 @@ + diff --git a/src/Tests/Nest.Tests.MockData/NestTestData.cs b/src/Tests/Nest.Tests.MockData/NestTestData.cs index fa3dcc3d868..03bc6c24c16 100644 --- a/src/Tests/Nest.Tests.MockData/NestTestData.cs +++ b/src/Tests/Nest.Tests.MockData/NestTestData.cs @@ -54,6 +54,7 @@ public static IGenerationSession Session .Setup(c => c.IntValues).Use() .Setup(c => c.FloatValues).Use() .Setup(c => c.LOC).Use() + .Setup(c => c.PingIP).Use() .Setup(c => c.Country).Use() .Setup(c => c.Origin).Use() .Setup(c => c.Name).Use() From a5058667184c3bfc9f761aab149aedf8c26e1252 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 3 Mar 2014 20:50:10 +0100 Subject: [PATCH 5/7] integration tests for all but nested aggregations --- .../DSL/Aggregations/AggregationDescriptor.cs | 6 +- .../GlobalAggregationDescriptor.cs | 10 +- .../HistogramAggregationDescriptor.cs | 2 +- .../Ip4RangeAggregationDescriptor.cs | 8 +- src/Nest/Domain/Aggregations/Bucket.cs | 14 ++ .../Aggregations/BucketAggregationBase.cs | 7 + .../Domain/Aggregations/DateHistogramItem.cs | 20 +++ .../Aggregations/ExtendedStatsMetric.cs | 14 ++ src/Nest/Domain/Aggregations/IAggration.cs | 104 ------------ .../Domain/Aggregations/IBucketAggregation.cs | 9 ++ src/Nest/Domain/Aggregations/IBucketItem.cs | 6 + .../Domain/Aggregations/IMetricAggregation.cs | 6 + src/Nest/Domain/Aggregations/KeyItem.cs | 8 + src/Nest/Domain/Aggregations/NestedBucket.cs | 6 + src/Nest/Domain/Aggregations/RangeItem.cs | 12 ++ src/Nest/Domain/Aggregations/SingleBucket.cs | 7 + src/Nest/Domain/Aggregations/StatsMetric.cs | 11 ++ src/Nest/Domain/Aggregations/ValueMetric.cs | 7 + src/Nest/Nest.csproj | 13 ++ .../Converters/AggregationConverter.cs | 152 +++++++++--------- .../Aggregations/BucketAggregationTests.cs | 152 ++++++++++++++++++ .../Aggregations/MetricAggregationTests.cs | 103 ++++++++++++ .../SingleBucketAggregationTests.cs | 63 ++++++++ .../Aggregations/StatsAggregationTests.cs | 64 ++++++++ .../Aggregations/TermsAggregationTests.cs | 17 +- .../Nest.Tests.Integration.csproj | 6 +- 26 files changed, 636 insertions(+), 191 deletions(-) create mode 100644 src/Nest/Domain/Aggregations/Bucket.cs create mode 100644 src/Nest/Domain/Aggregations/BucketAggregationBase.cs create mode 100644 src/Nest/Domain/Aggregations/DateHistogramItem.cs create mode 100644 src/Nest/Domain/Aggregations/ExtendedStatsMetric.cs create mode 100644 src/Nest/Domain/Aggregations/IBucketAggregation.cs create mode 100644 src/Nest/Domain/Aggregations/IBucketItem.cs create mode 100644 src/Nest/Domain/Aggregations/IMetricAggregation.cs create mode 100644 src/Nest/Domain/Aggregations/KeyItem.cs create mode 100644 src/Nest/Domain/Aggregations/NestedBucket.cs create mode 100644 src/Nest/Domain/Aggregations/RangeItem.cs create mode 100644 src/Nest/Domain/Aggregations/SingleBucket.cs create mode 100644 src/Nest/Domain/Aggregations/StatsMetric.cs create mode 100644 src/Nest/Domain/Aggregations/ValueMetric.cs create mode 100644 src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs create mode 100644 src/Tests/Nest.Tests.Integration/Aggregations/MetricAggregationTests.cs create mode 100644 src/Tests/Nest.Tests.Integration/Aggregations/SingleBucketAggregationTests.cs create mode 100644 src/Tests/Nest.Tests.Integration/Aggregations/StatsAggregationTests.cs diff --git a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs index fbaba79612b..fd36fe3c8be 100644 --- a/src/Nest/DSL/Aggregations/AggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/AggregationDescriptor.cs @@ -64,7 +64,7 @@ public AggregationDescriptor GeoDistance(string name, return _SetInnerAggregation(name, selector, (a, d) => a._GeoDistance = d); } - [JsonProperty("geo_hash")] + [JsonProperty("geohash_grid")] internal GeoHashAggregationDescriptor _GeoHash { get; set; } public AggregationDescriptor GeoHash(string name, Func, GeoHashAggregationDescriptor> selector) @@ -89,9 +89,9 @@ public AggregationDescriptor Global(string name, } [JsonProperty("ip_range")] - internal IpRangeAggregationDescriptor _IpRange { get; set; } + internal Ip4RangeAggregationDescriptor _IpRange { get; set; } public AggregationDescriptor IpRange(string name, - Func, IpRangeAggregationDescriptor> selector) + Func, Ip4RangeAggregationDescriptor> selector) { return _SetInnerAggregation(name, selector, (a, d) => a._IpRange = d); } diff --git a/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs index aeaf70374af..4e344d92c16 100644 --- a/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/GlobalAggregationDescriptor.cs @@ -1,10 +1,18 @@ +using Nest.Resolvers.Converters; using Newtonsoft.Json; namespace Nest { + [JsonConverter(typeof(CustomJsonConverter))] public class GlobalAggregationDescriptor : BucketAggregationBaseDescriptor, T> + , ICustomJson where T : class { - [JsonProperty("global")] internal readonly object _Global = new object {}; + internal readonly object _Global = new object {}; + + object ICustomJson.GetCustomJson() + { + return this._Global; + } } } \ No newline at end of file diff --git a/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs index f3caae900ae..278f6520da7 100644 --- a/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/HistogramAggregationDescriptor.cs @@ -7,7 +7,7 @@ namespace Nest { - public class HistogramAggregationDescriptor : MetricAggregationBaseDescriptor, T> + public class HistogramAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class { [JsonProperty("field")] diff --git a/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs index 65605d46006..49ca399f023 100644 --- a/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/Ip4RangeAggregationDescriptor.cs @@ -7,20 +7,20 @@ namespace Nest { - public class IpRangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> + public class Ip4RangeAggregationDescriptor : BucketAggregationBaseDescriptor, T> where T : class { [JsonProperty("field")] internal PropertyPathMarker _Field { get; set; } - public IpRangeAggregationDescriptor Field(string field) + public Ip4RangeAggregationDescriptor Field(string field) { this._Field = field; return this; } - public IpRangeAggregationDescriptor Field(Expression> field) + public Ip4RangeAggregationDescriptor Field(Expression> field) { this._Field = field; return this; @@ -29,7 +29,7 @@ public IpRangeAggregationDescriptor Field(Expression> field) [JsonProperty(PropertyName = "ranges")] internal IEnumerable _Ranges { get; set; } - public IpRangeAggregationDescriptor Ranges(params string[] ranges) + public Ip4RangeAggregationDescriptor Ranges(params string[] ranges) { var newRanges = from range in ranges let r = new Ip4Range().Mask(range) select r; this._Ranges = newRanges; diff --git a/src/Nest/Domain/Aggregations/Bucket.cs b/src/Nest/Domain/Aggregations/Bucket.cs new file mode 100644 index 00000000000..e47a941b752 --- /dev/null +++ b/src/Nest/Domain/Aggregations/Bucket.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Nest +{ + public class Bucket : BucketAggregationBase + where TBucketItem : IBucketItem + { + public IList Items { get; set; } + } + public class Bucket : IAggregation + { + public IEnumerable Items { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/BucketAggregationBase.cs b/src/Nest/Domain/Aggregations/BucketAggregationBase.cs new file mode 100644 index 00000000000..b57b8e9780e --- /dev/null +++ b/src/Nest/Domain/Aggregations/BucketAggregationBase.cs @@ -0,0 +1,7 @@ +namespace Nest +{ + public abstract class BucketAggregationBase : AggregationsHelper , IBucketAggregation + { + + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/DateHistogramItem.cs b/src/Nest/Domain/Aggregations/DateHistogramItem.cs new file mode 100644 index 00000000000..8724327f2d4 --- /dev/null +++ b/src/Nest/Domain/Aggregations/DateHistogramItem.cs @@ -0,0 +1,20 @@ +using System; + +namespace Nest +{ + public class DateHistogramItem : BucketAggregationBase, IBucketItem + { + public long Key { get; set; } + public string KeyAsString { get; set; } + + public DateTime Date + { + get + { + return new DateTime(1970, 1, 1).AddMilliseconds(0 + this.Key); + } + } + + public long DocCount { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/ExtendedStatsMetric.cs b/src/Nest/Domain/Aggregations/ExtendedStatsMetric.cs new file mode 100644 index 00000000000..b72b451099b --- /dev/null +++ b/src/Nest/Domain/Aggregations/ExtendedStatsMetric.cs @@ -0,0 +1,14 @@ +namespace Nest +{ + public class ExtendedStatsMetric : IMetricAggregation + { + public long Count { get; set; } + public double? Min { get; set; } + public double? Max { get; set; } + public double? Average { get; set; } + public double? Sum { get; set; } + public double? SumOfSquares { get; set; } + public double? Variance { get; set; } + public double? StdDeviation { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/IAggration.cs b/src/Nest/Domain/Aggregations/IAggration.cs index 72946815d55..66c3b998d5a 100644 --- a/src/Nest/Domain/Aggregations/IAggration.cs +++ b/src/Nest/Domain/Aggregations/IAggration.cs @@ -8,108 +8,4 @@ namespace Nest public interface IAggregation { } - - public interface IMetricAggregation : IAggregation - { - } - - public interface IBucketAggregation : IAggregation - { - IDictionary Aggregations { get; } - //AggregationsHelper Aggs { get; } - } - public abstract class BucketAggregationBase : AggregationsHelper , IBucketAggregation - { - //public IDictionary Aggregations { get; internal protected set; } - //private AggregationsHelper _agg = null; - - //public AggregationsHelper Aggs - //{ - // get { return _agg ?? (_agg = new AggregationsHelper(this.Aggregations)); } - //} - } - - public class ValueMetric : IMetricAggregation - { - public double Value { get; set; } - } - - public class StatsMetric : IMetricAggregation - { - public long Count { get; set; } - public double Min { get; set; } - public double Max { get; set; } - public double Average { get; set; } - public double Sum { get; set; } - } - - public class ExtendedStatsMetric : IMetricAggregation - { - public long Count { get; set; } - public double Min { get; set; } - public double Max { get; set; } - public double Average { get; set; } - public double Sum { get; set; } - public double SumOfSquares { get; set; } - public double Variance { get; set; } - public double StdDeviation { get; set; } - } - - - public class SingleBucket : BucketAggregationBase - { - public long DocCount { get; set; } - } - - public class NestedBucket : BucketAggregationBase - { - } - - public class Bucket : BucketAggregationBase - where TBucketItem : IBucketItem - { - public IList Items { get; set; } - } - - public class Bucket : IAggregation - { - public IEnumerable Items { get; set; } - } - - public interface IBucketItem : IAggregation - { - } - - public class KeyItem : BucketAggregationBase, IBucketItem - { - public string Key { get; set; } - public long DocCount { get; set; } - } - - public class DateHistogramItem : BucketAggregationBase, IBucketItem - { - public long Key { get; set; } - public string KeyAsString { get; set; } - - public DateTime Date - { - get - { - return new DateTime(1970, 1, 1).AddMilliseconds(0 + this.Key); - } - } - - public long DocCount { get; set; } - } - - public class RangeItem : BucketAggregationBase, IBucketItem - { - public string Key { get; set; } - public double? From { get; set; } - public string FromAsString { get; set; } - public double? To { get; set; } - public string ToAsString { get; set; } - public long DocCount { get; set; } - } - } diff --git a/src/Nest/Domain/Aggregations/IBucketAggregation.cs b/src/Nest/Domain/Aggregations/IBucketAggregation.cs new file mode 100644 index 00000000000..174b5cd6437 --- /dev/null +++ b/src/Nest/Domain/Aggregations/IBucketAggregation.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Nest +{ + public interface IBucketAggregation : IAggregation + { + IDictionary Aggregations { get; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/IBucketItem.cs b/src/Nest/Domain/Aggregations/IBucketItem.cs new file mode 100644 index 00000000000..aadd1f91aa0 --- /dev/null +++ b/src/Nest/Domain/Aggregations/IBucketItem.cs @@ -0,0 +1,6 @@ +namespace Nest +{ + public interface IBucketItem : IAggregation + { + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/IMetricAggregation.cs b/src/Nest/Domain/Aggregations/IMetricAggregation.cs new file mode 100644 index 00000000000..f697e64c519 --- /dev/null +++ b/src/Nest/Domain/Aggregations/IMetricAggregation.cs @@ -0,0 +1,6 @@ +namespace Nest +{ + public interface IMetricAggregation : IAggregation + { + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/KeyItem.cs b/src/Nest/Domain/Aggregations/KeyItem.cs new file mode 100644 index 00000000000..ba204617fc8 --- /dev/null +++ b/src/Nest/Domain/Aggregations/KeyItem.cs @@ -0,0 +1,8 @@ +namespace Nest +{ + public class KeyItem : BucketAggregationBase, IBucketItem + { + public string Key { get; set; } + public long DocCount { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/NestedBucket.cs b/src/Nest/Domain/Aggregations/NestedBucket.cs new file mode 100644 index 00000000000..805b8d2df35 --- /dev/null +++ b/src/Nest/Domain/Aggregations/NestedBucket.cs @@ -0,0 +1,6 @@ +namespace Nest +{ + public class NestedBucket : BucketAggregationBase + { + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/RangeItem.cs b/src/Nest/Domain/Aggregations/RangeItem.cs new file mode 100644 index 00000000000..0e5847642b1 --- /dev/null +++ b/src/Nest/Domain/Aggregations/RangeItem.cs @@ -0,0 +1,12 @@ +namespace Nest +{ + public class RangeItem : BucketAggregationBase, IBucketItem + { + public string Key { get; set; } + public double? From { get; set; } + public string FromAsString { get; set; } + public double? To { get; set; } + public string ToAsString { get; set; } + public long DocCount { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/SingleBucket.cs b/src/Nest/Domain/Aggregations/SingleBucket.cs new file mode 100644 index 00000000000..9906a31cb51 --- /dev/null +++ b/src/Nest/Domain/Aggregations/SingleBucket.cs @@ -0,0 +1,7 @@ +namespace Nest +{ + public class SingleBucket : BucketAggregationBase + { + public long DocCount { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/StatsMetric.cs b/src/Nest/Domain/Aggregations/StatsMetric.cs new file mode 100644 index 00000000000..01fb5e0fd78 --- /dev/null +++ b/src/Nest/Domain/Aggregations/StatsMetric.cs @@ -0,0 +1,11 @@ +namespace Nest +{ + public class StatsMetric : IMetricAggregation + { + public long Count { get; set; } + public double? Min { get; set; } + public double? Max { get; set; } + public double? Average { get; set; } + public double? Sum { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/ValueMetric.cs b/src/Nest/Domain/Aggregations/ValueMetric.cs new file mode 100644 index 00000000000..2f9714c346e --- /dev/null +++ b/src/Nest/Domain/Aggregations/ValueMetric.cs @@ -0,0 +1,7 @@ +namespace Nest +{ + public class ValueMetric : IMetricAggregation + { + public double? Value { get; set; } + } +} \ No newline at end of file diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index 34b5141b817..35f4ad97f66 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -94,7 +94,20 @@ + + + + + + + + + + + + + diff --git a/src/Nest/Resolvers/Converters/AggregationConverter.cs b/src/Nest/Resolvers/Converters/AggregationConverter.cs index b7dec751b39..184818e77d8 100644 --- a/src/Nest/Resolvers/Converters/AggregationConverter.cs +++ b/src/Nest/Resolvers/Converters/AggregationConverter.cs @@ -72,13 +72,13 @@ private IAggregation GetStatsAggregation(JsonReader reader, JsonSerializer seria reader.Read(); var count = (reader.Value as long?).GetValueOrDefault(0); reader.Read(); reader.Read(); - var min = (reader.Value as double?).GetValueOrDefault(0); + var min = (reader.Value as double?); reader.Read(); reader.Read(); - var max = (reader.Value as double?).GetValueOrDefault(0); + var max = (reader.Value as double?); reader.Read(); reader.Read(); - var average = (reader.Value as double?).GetValueOrDefault(0); + var average = (reader.Value as double?); reader.Read(); reader.Read(); - var sum = (reader.Value as double?).GetValueOrDefault(0); + var sum = (reader.Value as double?); reader.Read(); if (reader.TokenType == JsonToken.EndObject) @@ -92,11 +92,11 @@ private IAggregation GetStatsAggregation(JsonReader reader, JsonSerializer seria }; reader.Read(); - var sumOfSquares = (reader.Value as double?).GetValueOrDefault(0); + var sumOfSquares = (reader.Value as double?); reader.Read(); reader.Read(); - var variance = (reader.Value as double?).GetValueOrDefault(0); + var variance = (reader.Value as double?); reader.Read(); reader.Read(); - var stdVariation = (reader.Value as double?).GetValueOrDefault(0); + var stdVariation = (reader.Value as double?); reader.Read(); return new ExtendedStatsMetric() { @@ -127,68 +127,6 @@ private IAggregation GetDateHistogramAggregation(JsonReader reader, JsonSerializ } - public IAggregation GetRangeAggregation(JsonReader reader, JsonSerializer serializer, string key = null) - { - string fromAsString = null, toAsString = null; - long? docCount = null; - double? toDouble = null, fromDouble = null; - - var readExpectedProperty = true; - while (readExpectedProperty) - { - switch (reader.Value as string) - { - case "from": - reader.Read(); - if (reader.ValueType == typeof (double)) - fromDouble = (double) reader.Value; - reader.Read(); - break; - case "to": - reader.Read(); - if (reader.ValueType == typeof (double)) - toDouble = (double) reader.Value; - reader.Read(); - break; - case "key": - reader.Read(); - key = reader.Value as string; - reader.Read(); - break; - case "from_as_string": - reader.Read(); - fromAsString = reader.Value as string; - reader.Read(); - break; - case "to_as_string": - reader.Read(); - toAsString = reader.Value as string; - reader.Read(); - break; - case "doc_count": - reader.Read(); - docCount = (reader.Value as long?).GetValueOrDefault(0); - reader.Read(); - break; - default: - readExpectedProperty = false; - break; - } - } - var bucket = new RangeItem - { - Key = key, - From = fromDouble, - To = toDouble, - DocCount = docCount.GetValueOrDefault(), - FromAsString = fromAsString, - ToAsString = toAsString - }; - - bucket.Aggregations = this.GetNestedAggregations(reader, serializer); - return bucket; - - } private IAggregation GetKeyedBucketItem(JsonReader reader, JsonSerializer serializer) { @@ -238,7 +176,6 @@ private IAggregation GetBucketAggregation(JsonReader reader, JsonSerializer seri reader.Read(); if (reader.TokenType != JsonToken.StartArray) return null; - var currentDepth = reader.Depth; reader.Read(); //move from start array to start object if (reader.TokenType == JsonToken.EndArray) { @@ -248,11 +185,10 @@ private IAggregation GetBucketAggregation(JsonReader reader, JsonSerializer seri } do { - var agg = this.ReadAggregation(reader, serializer); aggregations.Add(agg); reader.Read(); - } while (reader.TokenType != JsonToken.EndArray);// && reader.Depth != currentDepth); + } while (reader.TokenType != JsonToken.EndArray); bucket.Items = aggregations; reader.Read(); return bucket; @@ -262,10 +198,13 @@ private IAggregation GetBucketAggregation(JsonReader reader, JsonSerializer seri private IAggregation GetValueMetricOrAggregation(JsonReader reader, JsonSerializer serializer) { reader.Read(); - //if (reader.TokenType = JsonToken.StartObject) - var metric = new ValueMetric() {Value = (reader.Value as double?).GetValueOrDefault(0)}; + var metric = new ValueMetric() + { + Value = (reader.Value as double?) + }; + if (metric.Value == null && reader.ValueType == typeof(long)) + metric.Value = reader.Value as long?; reader.Read(); - //todo value is a nested aggregation recurse. return metric; } @@ -279,5 +218,68 @@ public override bool CanConvert(Type objectType) { return objectType == typeof(IAggregation); } + + public IAggregation GetRangeAggregation(JsonReader reader, JsonSerializer serializer, string key = null) + { + string fromAsString = null, toAsString = null; + long? docCount = null; + double? toDouble = null, fromDouble = null; + + var readExpectedProperty = true; + while (readExpectedProperty) + { + switch (reader.Value as string) + { + case "from": + reader.Read(); + if (reader.ValueType == typeof (double)) + fromDouble = (double) reader.Value; + reader.Read(); + break; + case "to": + reader.Read(); + if (reader.ValueType == typeof (double)) + toDouble = (double) reader.Value; + reader.Read(); + break; + case "key": + reader.Read(); + key = reader.Value as string; + reader.Read(); + break; + case "from_as_string": + reader.Read(); + fromAsString = reader.Value as string; + reader.Read(); + break; + case "to_as_string": + reader.Read(); + toAsString = reader.Value as string; + reader.Read(); + break; + case "doc_count": + reader.Read(); + docCount = (reader.Value as long?).GetValueOrDefault(0); + reader.Read(); + break; + default: + readExpectedProperty = false; + break; + } + } + var bucket = new RangeItem + { + Key = key, + From = fromDouble, + To = toDouble, + DocCount = docCount.GetValueOrDefault(), + FromAsString = fromAsString, + ToAsString = toAsString + }; + + bucket.Aggregations = this.GetNestedAggregations(reader, serializer); + return bucket; + + } } } \ No newline at end of file diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs new file mode 100644 index 00000000000..2a8019b19d0 --- /dev/null +++ b/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs @@ -0,0 +1,152 @@ +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest.Tests.MockData.Domain; +using NUnit.Framework; + +namespace Nest.Tests.Integration.Aggregations +{ + [TestFixture] + public class BucketAggregationTests : IntegrationTests + { + [Test] + public void Terms() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .Terms("bucket_agg", m=>m.Field(p=>p.Country)) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.Terms("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + + [Test] + public void Histogram() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .Histogram("bucket_agg", m=>m + .Field(p=>p.IntValues) + .Interval(10) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.Histogram("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + [Test] + public void GeoHash() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .GeoHash("bucket_agg", m=>m + .Field(p=>p.Origin) + .GeoHashPrecision(GeoHashPrecision.precision_2) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.GeoHash("bucket_agg"); + bucket.Items.Should().NotBeEmpty() + .And.OnlyContain(i=>!i.Key.IsNullOrEmpty()); + } + [Test] + public void Range() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .Range("bucket_agg", m=>m + .Field(p=>p.LongValue) + .Ranges( + r=>r.To(10), + r=>r.From(10) + ) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.Range("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + [Test] + public void DateRange() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .DateRange("bucket_agg", m=>m + .Field(p=>p.StartedOn) + .Ranges( + r=>r.To("now-10M/M"), + r=>r.From("now-10M/M") + ) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.DateRange("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + [Test] + public void IpRange() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .IpRange("bucket_agg", dh=>dh + .Field(p=>p.PingIP) + .Ranges("10.0.0.0/25") + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.IpRange("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + [Test] + public void GeoDistance() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .GeoDistance("bucket_agg", dh=>dh + .Field(p=>p.Origin) + .Origin(28.0, 28.0) + .Unit(GeoUnit.km) + .Ranges( + r=>r.To(1), + r=>r.From(1).To(100) + ) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.GeoDistance("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + [Test] + public void DateHistogram() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .DateHistogram("bucket_agg", dh=>dh + .Field(p=>p.StartedOn) + .Interval("1d") + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.DateHistogram("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + + } +} \ No newline at end of file diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/MetricAggregationTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/MetricAggregationTests.cs new file mode 100644 index 00000000000..7e25e963f11 --- /dev/null +++ b/src/Tests/Nest.Tests.Integration/Aggregations/MetricAggregationTests.cs @@ -0,0 +1,103 @@ +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest.Tests.MockData.Domain; +using NUnit.Framework; + +namespace Nest.Tests.Integration.Aggregations +{ + [TestFixture] + public class MetricAggregationTests : IntegrationTests + { + [Test] + public void WrongFieldName() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Min("value_agg", t=>t + .Field("this_field_name_does_not_exist") + ) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Min("value_agg"); + termBucket.Should().NotBeNull(); + termBucket.Value.Should().NotHaveValue(); + } + + [Test] + public void Average() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Average("value_agg", t=>t.Field(p=>p.LOC)) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Min("value_agg"); + termBucket.Should().NotBeNull(); + termBucket.Value.Should().HaveValue(); + } + [Test] + public void Min() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Min("value_agg", t=>t.Field(p=>p.LOC)) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Min("value_agg"); + termBucket.Should().NotBeNull(); + termBucket.Value.Should().HaveValue(); + } + + [Test] + public void Max() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Max("value_agg", t=>t.Field(p=>p.LOC)) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Max("value_agg"); + termBucket.Should().NotBeNull(); + termBucket.Value.Should().HaveValue(); + } + + [Test] + public void Sum() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Sum("value_agg", t=>t.Field(p=>p.LOC)) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.Sum("value_agg"); + termBucket.Should().NotBeNull(); + termBucket.Value.Should().HaveValue(); + } + + [Test] + public void ValueCount() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .ValueCount("value_agg", t=>t.Field(p=>p.LOC)) + ) + ); + results.IsValid.Should().BeTrue(); + var termBucket = results.Aggs.ValueCount("value_agg"); + termBucket.Should().NotBeNull(); + termBucket.Value.Should().HaveValue(); + } + } +} \ No newline at end of file diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/SingleBucketAggregationTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/SingleBucketAggregationTests.cs new file mode 100644 index 00000000000..68ed704aa68 --- /dev/null +++ b/src/Tests/Nest.Tests.Integration/Aggregations/SingleBucketAggregationTests.cs @@ -0,0 +1,63 @@ +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest.Tests.MockData.Domain; +using NUnit.Framework; + +namespace Nest.Tests.Integration.Aggregations +{ + [TestFixture] + public class SingleBucketAggregationTests : IntegrationTests + { + [Test] + public void Missing() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .Missing("miss_me", m=>m.Field("not_really")) + ) + ); + results.IsValid.Should().BeTrue(); + var missingBucket = results.Aggs.Missing("miss_me"); + missingBucket.DocCount.Should().BeGreaterThan(1); + } + + [Test] + public void Filter() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .Filter("filtered_agg", m=>m + .Filter(f=>f.Term(p=>p.Country, "Sweden")) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var filteredBucket = results.Aggs.Filter("filtered_agg"); + filteredBucket.DocCount.Should().BeGreaterThan(1); + } + + [Test] + public void Global() + { + var results = this._client.Search(s=>s + .Size(0) + .Query(q=>q.Term(p=>p.Name, "There is no name like this")) + .Aggregations(a=>a + .Global("global", g=>g + .Aggregations(aa=>aa + .ValueCount("name",n=>n.Field(p=>p.Name)) + ) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var global = results.Aggs.Global("global"); + global.DocCount.Should().BeGreaterThan(1); + var valueCount = global.ValueCount("name"); + valueCount.Value.Should().BeGreaterThan(1); + } + } +} \ No newline at end of file diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/StatsAggregationTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/StatsAggregationTests.cs new file mode 100644 index 00000000000..59947f7bd5c --- /dev/null +++ b/src/Tests/Nest.Tests.Integration/Aggregations/StatsAggregationTests.cs @@ -0,0 +1,64 @@ +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest.Tests.MockData.Domain; +using NUnit.Framework; + +namespace Nest.Tests.Integration.Aggregations +{ + [TestFixture] + public class StatsAggregation : IntegrationTests + { + [Test] + public void WrongFieldName() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Stats("stats_agg", t=>t + .Field("this_field_name_does_not_exist") + ) + ) + ); + results.IsValid.Should().BeTrue(); + var statsBucket = results.Aggs.Stats("stats_agg"); + statsBucket.Should().NotBeNull(); + statsBucket.Count.Should().Be(0); + statsBucket.Sum.Should().NotHaveValue(); + } + + [Test] + public void Average() + { + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .Stats("stats_agg", t=>t.Field(p=>p.LOC)) + ) + ); + results.IsValid.Should().BeTrue(); + var statsBucket = results.Aggs.Stats("stats_agg"); + statsBucket.Should().NotBeNull(); + statsBucket.Count.Should().BeGreaterThan(1); + statsBucket.Sum.Should().BeGreaterThan(1); + } + + [Test] + public void ExtendedStats() + { + + var results = this._client.Search(s => s + .Size(0) + .Aggregations(a=>a + .ExtendedStats("stats_agg", t=>t.Field(p=>p.LOC)) + ) + ); + results.IsValid.Should().BeTrue(); + var statsBucket = results.Aggs.ExtendedStats("stats_agg"); + statsBucket.Should().NotBeNull(); + statsBucket.Count.Should().BeGreaterThan(1); + statsBucket.StdDeviation.Should().BeGreaterThan(1); + } + + } +} \ No newline at end of file diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs index d3f55f193df..b580187afd2 100644 --- a/src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs +++ b/src/Tests/Nest.Tests.Integration/Aggregations/TermsAggregationTests.cs @@ -46,7 +46,7 @@ public void ExistingFieldName() } [Test] - public void NestedEmptyAggregation() + public void NestedEmptyAggregationThreeLevelDeeps() { var results = this._client.Search(s => s .Size(0) @@ -55,7 +55,12 @@ public void NestedEmptyAggregation() .Field(p=>p.Country) .Aggregations(aa=>aa .Terms("noop", tt => tt.Field("noop")) - .Terms("names", tt => tt.Field(p=>p.Name)) + .Terms("names", tt => tt + .Field(p=>p.Name) + .Aggregations(aaa=>aaa + .Average("avg_loc", avg=>avg .Field(p=>p.LOC)) + ) + ) ) ) ) @@ -79,6 +84,14 @@ public void NestedEmptyAggregation() var names = term.Terms("names"); names.Should().NotBeNull(); names.Items.Should().NotBeEmpty(); + + foreach (var nameTerm in names.Items) + { + var name = nameTerm.Key; + var average = nameTerm.Average("avg_loc"); + average.Should().NotBeNull(); + average.Value.Should().HaveValue(); + } } } } diff --git a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj index f60651d5db3..b5fefdf4631 100644 --- a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj +++ b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj @@ -68,7 +68,11 @@ - + + + + + From ca3578e6cc6a4507254a52875fb510862f1b36be Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 3 Mar 2014 20:59:01 +0100 Subject: [PATCH 6/7] started on nested aggregation --- .../BucketAggregationTests - Copy.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests - Copy.cs diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests - Copy.cs b/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests - Copy.cs new file mode 100644 index 00000000000..cfb9977743a --- /dev/null +++ b/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests - Copy.cs @@ -0,0 +1,31 @@ +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest.Tests.MockData.Domain; +using NUnit.Framework; + +namespace Nest.Tests.Integration.Aggregations +{ + [TestFixture] + public class NestedBucketAggregationTests : IntegrationTests + { + [Test] + public void Terms() + { + var results = this._client.Search(s=>s + .Size(0) + .Aggregations(a=>a + .Nested("followers", n=>n + .Aggregations(t=>t + .Terms("bucket_agg", m=>m.Field(p=>p.Country)) + ) + ) + ) + ); + results.IsValid.Should().BeTrue(); + var bucket = results.Aggs.Terms("bucket_agg"); + bucket.Items.Should().NotBeEmpty(); + } + + } +} \ No newline at end of file From 13c91bd56ac1e59e08846d6416fd8b2013f81a73 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 3 Mar 2014 21:27:49 +0100 Subject: [PATCH 7/7] added support for nested aggregation type --- .../Aggregations/NestedAggregationDescriptor.cs | 9 ++++++++- .../Domain/Aggregations/AggregationsHelper.cs | 4 ++-- src/Nest/Domain/Aggregations/NestedBucket.cs | 8 ++++++-- src/Nest/Domain/Aggregations/SingleBucket.cs | 7 ------- src/Nest/Nest.csproj | 1 - .../Aggregations/BucketAggregationTests.cs | 1 + ...- Copy.cs => NestedBucketAggregationTests.cs} | 16 ++++++++++++---- .../Aggregations/ParseResponseItemsTests.cs | 1 - .../Nest.Tests.Integration.csproj | 3 ++- .../Nest.Tests.MockData/DataSources/AgeSource.cs | 16 ++++++++++++++++ .../Domain/ElasticsearchProject.cs | 3 +++ .../Nest.Tests.MockData.csproj | 1 + src/Tests/Nest.Tests.MockData/NestTestData.cs | 5 +++++ 13 files changed, 56 insertions(+), 19 deletions(-) delete mode 100644 src/Nest/Domain/Aggregations/SingleBucket.cs rename src/Tests/Nest.Tests.Integration/Aggregations/{BucketAggregationTests - Copy.cs => NestedBucketAggregationTests.cs} (55%) create mode 100644 src/Tests/Nest.Tests.MockData/DataSources/AgeSource.cs diff --git a/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs b/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs index c5d7356c2bc..b6965ba0cf7 100644 --- a/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs +++ b/src/Nest/DSL/Aggregations/NestedAggregationDescriptor.cs @@ -1,11 +1,14 @@ using System; using System.Linq.Expressions; using Nest.Resolvers; +using Nest.Resolvers.Converters; using Newtonsoft.Json; namespace Nest { + [JsonConverter(typeof(CustomJsonConverter))] public class NestedAggregationDescriptor : BucketAggregationBaseDescriptor, T> + , ICustomJson where T : class { internal class NestedAgg @@ -14,7 +17,6 @@ internal class NestedAgg internal PropertyPathMarker _Path; } - [JsonProperty("nested")] internal NestedAgg _Nested; @@ -31,5 +33,10 @@ public NestedAggregationDescriptor Path(Expression> path) this._Nested._Path = path; return this; } + + object ICustomJson.GetCustomJson() + { + return this._Nested; + } } } \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/AggregationsHelper.cs b/src/Nest/Domain/Aggregations/AggregationsHelper.cs index 6fc5822b3ec..3c5ae4129cf 100644 --- a/src/Nest/Domain/Aggregations/AggregationsHelper.cs +++ b/src/Nest/Domain/Aggregations/AggregationsHelper.cs @@ -77,9 +77,9 @@ public SingleBucket Missing(string key) return this.TryGet(key); } - public NestedBucket Nested(string key) + public SingleBucket Nested(string key) { - return this.TryGet(key); + return this.TryGet(key); } public Bucket Terms(string key) diff --git a/src/Nest/Domain/Aggregations/NestedBucket.cs b/src/Nest/Domain/Aggregations/NestedBucket.cs index 805b8d2df35..9cace750310 100644 --- a/src/Nest/Domain/Aggregations/NestedBucket.cs +++ b/src/Nest/Domain/Aggregations/NestedBucket.cs @@ -1,6 +1,10 @@ -namespace Nest +using Newtonsoft.Json; + +namespace Nest { - public class NestedBucket : BucketAggregationBase + public class SingleBucket : BucketAggregationBase { + [JsonProperty("doc_count")] + public long DocCount { get; set; } } } \ No newline at end of file diff --git a/src/Nest/Domain/Aggregations/SingleBucket.cs b/src/Nest/Domain/Aggregations/SingleBucket.cs deleted file mode 100644 index 9906a31cb51..00000000000 --- a/src/Nest/Domain/Aggregations/SingleBucket.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Nest -{ - public class SingleBucket : BucketAggregationBase - { - public long DocCount { get; set; } - } -} \ No newline at end of file diff --git a/src/Nest/Nest.csproj b/src/Nest/Nest.csproj index 35f4ad97f66..b7ba3a0baa3 100644 --- a/src/Nest/Nest.csproj +++ b/src/Nest/Nest.csproj @@ -105,7 +105,6 @@ - diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs index 2a8019b19d0..87d97277892 100644 --- a/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs +++ b/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests.cs @@ -33,6 +33,7 @@ public void Histogram() .Field(p=>p.IntValues) .Interval(10) ) + ) ); results.IsValid.Should().BeTrue(); diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests - Copy.cs b/src/Tests/Nest.Tests.Integration/Aggregations/NestedBucketAggregationTests.cs similarity index 55% rename from src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests - Copy.cs rename to src/Tests/Nest.Tests.Integration/Aggregations/NestedBucketAggregationTests.cs index cfb9977743a..5a35f70005d 100644 --- a/src/Tests/Nest.Tests.Integration/Aggregations/BucketAggregationTests - Copy.cs +++ b/src/Tests/Nest.Tests.Integration/Aggregations/NestedBucketAggregationTests.cs @@ -15,16 +15,24 @@ public void Terms() var results = this._client.Search(s=>s .Size(0) .Aggregations(a=>a - .Nested("followers", n=>n + .Nested("contributors", n=>n + .Path(p=>p.Contributors) .Aggregations(t=>t - .Terms("bucket_agg", m=>m.Field(p=>p.Country)) + .Average("avg_age", m=>m + .Field(p=>p.Contributors.First().Age) + ) ) ) ) ); results.IsValid.Should().BeTrue(); - var bucket = results.Aggs.Terms("bucket_agg"); - bucket.Items.Should().NotBeEmpty(); + var bucket = results.Aggs.Nested("contributors"); + bucket.DocCount.Should().BeGreaterThan(1); + + var averageAge = bucket.Average("avg_age"); + averageAge.Should().NotBeNull(); + averageAge.Value.Should().HaveValue() + .And.BeGreaterOrEqualTo(18); } } diff --git a/src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs b/src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs index afad2c5a181..62721e1afff 100644 --- a/src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs +++ b/src/Tests/Nest.Tests.Integration/Aggregations/ParseResponseItemsTests.cs @@ -112,7 +112,6 @@ public void GeoDistanceItem() .Aggregations(a=>a .GeoDistance("my_geod", dh=>dh .Field(p=>p.Origin) - //.DistanceType(GeoDistanceType.sloppy_arc) .Origin(28.0, 28.0) .Unit(GeoUnit.km) .Ranges( diff --git a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj index b5fefdf4631..ffac1dd79d1 100644 --- a/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj +++ b/src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj @@ -68,8 +68,9 @@ - + + diff --git a/src/Tests/Nest.Tests.MockData/DataSources/AgeSource.cs b/src/Tests/Nest.Tests.MockData/DataSources/AgeSource.cs new file mode 100644 index 00000000000..7886b48db79 --- /dev/null +++ b/src/Tests/Nest.Tests.MockData/DataSources/AgeSource.cs @@ -0,0 +1,16 @@ +using System; +using AutoPoco.Engine; + +namespace Nest.Tests.MockData.DataSources +{ + public class AgeSource : DatasourceBase + { + private Random mRandom = new Random(1337); + public override int Next(IGenerationSession session) + { + int f = mRandom.Next(18, 99); + return f; + } + + } +} \ No newline at end of file diff --git a/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs b/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs index 3aa3099e4fc..e151e6495c1 100644 --- a/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs +++ b/src/Tests/Nest.Tests.MockData/Domain/ElasticsearchProject.cs @@ -22,6 +22,9 @@ public class ElasticsearchProject public int LOC { get; set; } public List Followers { get; set; } + [ElasticProperty(Type=FieldType.nested)] + public List Contributors { get; set; } + public List NestedFollowers { get; set; } [ElasticProperty(Type=FieldType.geo_point)] diff --git a/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj b/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj index d0b795eb98e..9c0a3a31181 100644 --- a/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj +++ b/src/Tests/Nest.Tests.MockData/Nest.Tests.MockData.csproj @@ -73,6 +73,7 @@ + diff --git a/src/Tests/Nest.Tests.MockData/NestTestData.cs b/src/Tests/Nest.Tests.MockData/NestTestData.cs index 03bc6c24c16..0dfb786b7e3 100644 --- a/src/Tests/Nest.Tests.MockData/NestTestData.cs +++ b/src/Tests/Nest.Tests.MockData/NestTestData.cs @@ -44,6 +44,7 @@ public static IGenerationSession Session .Setup(c => c.FirstName).Use() .Setup(c => c.LastName).Use() .Setup(c => c.DateOfBirth).Use() + .Setup(c => c.Age).Use() .Setup(c => c.PlaceOfBirth).Use(); x.Include() .Setup(c => c.Id).Use() @@ -59,6 +60,7 @@ public static IGenerationSession Session .Setup(c => c.Origin).Use() .Setup(c => c.Name).Use() .Setup(c => c.Followers).Value(new List()) + .Setup(c => c.Contributors).Value(new List()) .Setup(c => c.StartedOn).Use() .Setup(c => c.Content).Use(); }); @@ -100,6 +102,7 @@ public static IEnumerable Data // Get a single user var count = ElasticsearchProjectsDataSource.Count(); var users = Session.List(100).Get(); + var contributors = Session.List(100).Get(); _Data = Session.List(count).Get(); var i = 0; foreach (var p in _Data) @@ -107,6 +110,8 @@ public static IEnumerable Data var take = (int)100 / count; var skip = i * take; var followers = users.Skip(i * take).Take(take).ToList(); + var cont = contributors.Skip(i * take).Take(take).ToList(); + p.Contributors = cont; p.Followers = followers; i++; }