Generally speaking, method calls using the Fluent lambda expression syntax within NEST perform assignment as opposed to being additive, meaning that successive calls of the same method will overwrite what is assigned. In your example here
SearchDescriptor<object> SearchAgg = new SearchDescriptor<object>();
for (i=0;i < aggList.length;i++)
{
SearchAgg.Aggregations(a => a.terms (aggList[i]), t=> t.Field(aggList[i]));
}
only the last call to SearchAgg.Aggregations(...)
will assign.
The writing aggregations documentation has examples of issuing multiple aggregations. Given the following POCOs
public class Project
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime StartedOn { get; set; }
public DateTime LastActivity { get; set; }
public IList<string> Tags { get; set; }
public IList<string> Branches { get; set; }
public IList<CommitActivity> Commits { get; set; }
}
public class CommitActivity
{
public string Id { get; set; }
public string Message { get; set; }
public long SizeInBytes { get; set; }
}
where CommitActivity
is mapped as a nested
type, issuing two terms aggregation with a nested aggregation on commits to aggregate stats about commits for each project
Using fluent lambda expression syntax
var searchResponse = client.Search<Project>(s => s
.Aggregations(aggs => aggs
.Terms("project_tags", t => t.Field(p => p.Tags))
.Terms("project_branches", t => t.Field(p => p.Branches))
.Nested("commits", n => n
.Path(p => p.Commits)
.Aggregations(aa => aa
.Stats("commit_size_stats", m => m.Field(p => p.Commits.First().SizeInBytes))
)
)
)
);
Object Initializer syntax
var searchRequest = new SearchRequest<Project>
{
Aggregations = new AggregationDictionary
{
{ "project_tags", new TermsAggregation("project_tags") { Field = Nest.Infer.Field<Project>(p => p.Tags) } },
{ "project_branches", new TermsAggregation("project_branches") { Field = Nest.Infer.Field<Project>(p => p.Branches) } },
{ "commits", new NestedAggregation("commits")
{
Path = Nest.Infer.Field<Project>(p => p.Commits),
Aggregations = new AggregationDictionary
{
{ "commit_size_stats", new StatsAggregation("commit_size_stats", Nest.Infer.Field<Project>(p => p.Commits.First().SizeInBytes)) },
}
}
}
}
};
var searchResponse = client.Search<Project>(searchRequest);
Since ultimately aggregations on a search request is just a dictionary of aggregation name and the type of aggregation, using this syntax can grow big very quickly. for this reason, NEST overloads the logical &&
operator and implements implicit conversions to allow combining aggregations in a more terse fashion
Terse Object Initializer syntax
var searchRequest = new SearchRequest<Project>
{
Aggregations =
new TermsAggregation("project_tags") { Field = Nest.Infer.Field<Project>(p => p.Tags) } &&
new TermsAggregation("project_branches") { Field = Nest.Infer.Field<Project>(p => p.Branches) } &&
new NestedAggregation("commits")
{
Path = Nest.Infer.Field<Project>(p => p.Commits),
Aggregations =
new StatsAggregation("commit_size_stats", Nest.Infer.Field<Project>(p => p.Commits.First().SizeInBytes))
}
};
var searchResponse = client.Search<Project>(searchRequest);