问题描述
我需要使用nesT从文档中返回所有类别的disTINCTS(无重复)。
在sql中,它看起来像这样:
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 5.8 3 4.35 1.3
在ElasticSearch内部,我这样做:
SELECT disTINCT Category
FROM Log
ORDER BY Category ASC
如何使用nesT做到这一点?
GET log/_search
{
"size":"0","aggs" : {
"alias_category" : {
"terms" : { "field" : "category.keyword" }
}
}
}
解决方法
我找到了一种方法。这不是一种优雅的方法,但是我在Elastico网站(https://discuss.elastic.co/t/c-nest-best-way-of-accessing-properties-of-iaggregate-object/85384/2)中发现了,并且这样做是这样的:
public ICollection<string> SelectAllCategoriesDistinct(ElasticClient client)
{
var searchResponse =
client.Search<LogElasticSearch>(s => s
.Size(0)
.Aggregations(agg => agg
.Terms("categories",t => t
.Field("category.keyword")
)
)
);
var aggregation = searchResponse.Aggregations.Values;
var listOfCategories = new List<string>();
if (searchResponse.Aggregations.Values.FirstOrDefault().GetType() == typeof(BucketAggregate))
{
foreach (IBucket bucket in ((BucketAggregate)aggregation.FirstOrDefault()).Items)
{
if (bucket.GetType() == typeof(KeyedBucket<object>))
{
var valueKey = ((KeyedBucket<object>)bucket).Key;
listOfCategories.Add(valueKey.ToString());
}
}
}
return listOfCategories.OrderBy(c => c).ToList();
}
如果有人知道更好的方法,请帮助我进行改进,但是那样就可以达到目标。
,我将使用composite aggregation来获取所有条款。与terms aggregation相比,复合聚合支持分页,因此,如果有 lot 项要提取
,则可以进行多个请求private static void Main()
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool);
var client = new ElasticClient(settings);
var categories = new List<string>();
GetAllCategories(client,categories);
// do something with the categories
foreach(var category in categories)
Console.WriteLine(category);
}
private static void GetAllCategories(IElasticClient client,List<string> categories,CompositeKey after = null)
{
// number of terms to fetch in each request
var size = 10_000;
var response = client.Search<LogElasticSearch>(s => s
.Size(0)
.Aggregations(a => a
.Composite("categories",c => c
.After(after)
.Size(size)
.Sources(so => so
.Terms("category",t => t
.Field("category.keyword")
.Order(SortOrder.Ascending)
)
)
)
)
);
var compositeAgg = response.Aggregations.Composite("categories");
var buckets = compositeAgg.Buckets;
foreach (var bucket in buckets)
{
if (bucket.Key.TryGetValue("category",out string category))
{
categories.Add(category);
}
}
// there may be more
if (buckets.Count == size)
{
GetAllCategories(client,categories,compositeAgg.AfterKey);
}
}