-
-
Notifications
You must be signed in to change notification settings - Fork 21
Add support for nested query and nested aggregation #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
764efd1
73a4f6e
75b02e8
9f4afa8
9a4f487
93f975f
6cf99c8
c6c1d11
b4b8fa7
7a5f867
3c03030
701e014
869e511
d1ba0dd
e193a9d
1d66689
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Nest; | ||
|
|
||
| namespace Foundatio.Parsers.ElasticQueries.Extensions; | ||
|
|
@@ -7,13 +8,59 @@ public static class SearchDescriptorExtensions | |
| { | ||
| public static SearchDescriptor<T> Aggregations<T>(this SearchDescriptor<T> descriptor, AggregationContainer aggregations) where T : class | ||
| { | ||
| descriptor.Aggregations(f => | ||
| return descriptor.Aggregations(f => CopyAggregations(f, aggregations.Aggregations)); | ||
| } | ||
|
|
||
| public static AggregationContainerDescriptor<T> CopyAggregations<T>( | ||
| AggregationContainerDescriptor<T> target, | ||
| IDictionary<string, IAggregationContainer> sourceAggregations | ||
| ) where T : class | ||
| { | ||
| foreach (var kvp in sourceAggregations) | ||
| { | ||
| ((IAggregationContainer)f).Aggregations = aggregations.Aggregations; | ||
| return f; | ||
| }); | ||
| string name = kvp.Key; | ||
| var agg = kvp.Value; | ||
|
|
||
| return descriptor; | ||
| if (agg.Nested != null) | ||
| { | ||
| // Nested aggregation: copy nested path and inner aggregations recursively | ||
| target.Nested(name, n => n | ||
| .Path(agg.Nested.Path) | ||
| .Aggregations(a => CopyAggregations(a, agg.Nested.Aggregations))); | ||
| } | ||
| else if (agg.Terms != null) | ||
| { | ||
| target.Terms(name, t => | ||
| { | ||
| // Copy field | ||
| if (agg.Terms.Field != null) | ||
| t.Field(agg.Terms.Field); | ||
|
|
||
| // Copy exclude | ||
| if (agg.Terms.Exclude != null) | ||
| { | ||
| if (agg.Terms.Exclude.Values != null && agg.Terms.Exclude.Values.Count() > 0) | ||
| { | ||
| t.Exclude([.. agg.Terms.Exclude.Values]); | ||
| } | ||
| } | ||
|
|
||
| // Copy Meta if present | ||
| if (agg.Meta != null) | ||
veeraagandhi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| t.Meta(d => { | ||
| foreach (var meta in agg.Terms.Meta) | ||
| d.Add(meta.Key, meta.Value); | ||
| return d; | ||
| }); | ||
| } | ||
|
Comment on lines
+76
to
+84
|
||
|
|
||
| return t; | ||
| }); | ||
| } | ||
| } | ||
|
Comment on lines
+14
to
+110
|
||
|
|
||
| return target; | ||
| } | ||
|
|
||
| public static SearchDescriptor<T> Sort<T>(this SearchDescriptor<T> descriptor, IEnumerable<ISort> sorts) where T : class | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -22,6 +22,9 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte | |||||
| var container = await GetParentContainerAsync(node, context); | ||||||
| var termsAggregation = container as ITermsAggregation; | ||||||
|
|
||||||
| var parentBucket = container as BucketAggregationBase; | ||||||
| var childAggregations = new Dictionary<string, AggregationContainer>(); | ||||||
|
|
||||||
| foreach (var child in node.Children.OfType<IFieldQueryNode>()) | ||||||
| { | ||||||
| var aggregation = await child.GetAggregationAsync(() => child.GetDefaultAggregationAsync(context)); | ||||||
|
|
@@ -30,7 +33,7 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte | |||||
| var termNode = child as TermNode; | ||||||
| if (termNode != null && termsAggregation != null) | ||||||
| { | ||||||
| // TODO: Move these to the default aggs method using a visitor to walk down the tree to gather them but not going into any sub groups | ||||||
| // Accumulate @exclude values as a list | ||||||
| if (termNode.Field == "@exclude") | ||||||
| { | ||||||
| termsAggregation.Exclude = termsAggregation.Exclude.AddValue(termNode.UnescapedTerm); | ||||||
|
|
@@ -45,11 +48,8 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte | |||||
| } | ||||||
| else if (termNode.Field == "@min") | ||||||
| { | ||||||
| int? minCount = null; | ||||||
| if (!String.IsNullOrEmpty(termNode.Term) && Int32.TryParse(termNode.UnescapedTerm, out int parsedMinCount)) | ||||||
| minCount = parsedMinCount; | ||||||
|
|
||||||
| termsAggregation.MinimumDocumentCount = minCount; | ||||||
| if (!string.IsNullOrEmpty(termNode.Term) && Int32.TryParse(termNode.UnescapedTerm, out int parsedMinCount)) | ||||||
| termsAggregation.MinimumDocumentCount = parsedMinCount; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
|
|
@@ -78,7 +78,7 @@ public override async Task VisitAsync(GroupNode node, IQueryVisitorContext conte | |||||
| if (termNode.Field == "@missing") | ||||||
| { | ||||||
| DateTime? missingValue = null; | ||||||
| if (!String.IsNullOrEmpty(termNode.Term) && DateTime.TryParse(termNode.Term, out var parsedMissingDate)) | ||||||
| if (!string.IsNullOrEmpty(termNode.Term) && DateTime.TryParse(termNode.Term, out var parsedMissingDate)) | ||||||
|
||||||
| if (!string.IsNullOrEmpty(termNode.Term) && DateTime.TryParse(termNode.Term, out var parsedMissingDate)) | |
| if (!String.IsNullOrEmpty(termNode.Term) && DateTime.TryParse(termNode.Term, out var parsedMissingDate)) |
Uh oh!
There was an error while loading. Please reload this page.