Csharp/C#教程:ElasticSearch Nest。 更好的术语聚合代码及其迭代分享


ElasticSearch Nest。 更好的术语聚合代码及其迭代

我想在给定时间段内获取唯一数字用户ID列表。

假设该字段为userId ,时间字段为startTime ,我成功获得如下结果;

 HashSet hashUserIdList= new HashSet(); // guarantees to store unique userIds. // Step 1. get unique number of userIds var total = client.Search(s => s .Query(q => q .DateRange(c => c.Field(p => p.startTime) .GreaterThan(FixedDate))) .Aggregations(a => a .Cardinality("userId_cardinality", c => c .Field("userId")))) .Aggs.Cardinality("userId_cardinality"); int totalCount = (int)total.Value; // Step 2. get unique userId values by Terms aggregation. var response = client.Search(s => s .Source(source => source.Includes(inc => inc.Field("userId"))) .Query(q => q .DateRange(c => c.Field(p => p.startTime) .GreaterThan(FixedDate))) .Aggregations(a => a .Terms("userId_terms", c => c .Field("userId").Size(totalCount)))) .Aggs.Terms("userId_terms"); // Step 3. store unique userIds to HashSet. foreach (var element in response.Buckets) { hashUserIdList.Add(int.Parse(element.Key)); } 

工作但看起来效率不高,因为(1)它首先获取totalCount ,(2)它定义了Size(totalCount) ,由于存储桶溢出可能导致500服务器错误(如果结果有数千,则该怎么办)。

foreach方式迭代会很好,但我没能使它们按100的大小进行迭代。 我把From / SizeSkip / Take放在这里,但返回的值不可靠。

我怎样才能正确编码?

对于某些集合,这种方法可能没问题,但有几点意见:

  1. 基数聚合使用HyperLogLog ++算法来逼近基数; 对于低基数字段,这种近似可以是完全准确的,但对于高基数字则则不那么准确。
  2. 术语聚合对于许多术语来说可能在计算上是昂贵的,因为每个桶需要在内存中构建,然后序列化为响应。

您可以跳过基数聚合来获取大小,并简单地将int.MaxValue作为术语聚合的大小传递。 另一种在速度方面效率较低的方法是滚动浏览范围内的所有文档,源filter只返回您感兴趣的字段。我希望Scroll方法可以减少对集群的压力,但我建议您监控您采取的任何方法。

下面是Stack Overflow数据集(2016年6月,IIRC)的两种方法的比较,看看2年前的今天和今年之前的独特问题。

术语聚合

 void Main() { var pool = new SingleNodeConnectionPool(new Uri("https://localhost:9200")); var connectionSettings = new ConnectionSettings(pool) .MapDefaultTypeIndices(d => d .Add(typeof(Question), NDC.StackOverflowIndex) ); var client = new ElasticClient(connectionSettings); var twoYearsAgo = DateTime.UtcNow.Date.AddYears(-2); var yearAgo = DateTime.UtcNow.Date.AddYears(-1); var searchResponse = client.Search(s => s .Size(0) .Query(q => q .DateRange(c => c.Field(p => p.CreationDate) .GreaterThan(twoYearsAgo) .LessThan(yearAgo) ) ) .Aggregations(a => a .Terms("unique_users", c => c .Field(f => f.OwnerUserId) .Size(int.MaxValue) ) ) ); var uniqueOwnerUserIds = searchResponse.Aggs.Terms("unique_users").Buckets.Select(b => b.KeyAsString).ToList(); // 3.83 seconds // unique question askers: 795352 Console.WriteLine($"unique question askers: {uniqueOwnerUserIds.Count}"); } 

Scroll API

 void Main() { var pool = new SingleNodeConnectionPool(new Uri("https://localhost:9200")); var connectionSettings = new ConnectionSettings(pool) .MapDefaultTypeIndices(d => d .Add(typeof(Question), NDC.StackOverflowIndex) ); var client = new ElasticClient(connectionSettings); var uniqueOwnerUserIds = new HashSet(); var twoYearsAgo = DateTime.UtcNow.Date.AddYears(-2); var yearAgo = DateTime.UtcNow.Date.AddYears(-1); var searchResponse = client.Search(s => s .Source(sf => sf .Include(ff => ff .Field(f => f.OwnerUserId) ) ) .Size(10000) .Scroll("1m") .Query(q => q .DateRange(c => c .Field(p => p.CreationDate) .GreaterThan(twoYearsAgo) .LessThan(yearAgo) ) ) ); while (searchResponse.Documents.Any()) { foreach (var document in searchResponse.Documents) { if (document.OwnerUserId.HasValue) uniqueOwnerUserIds.Add(document.OwnerUserId.Value); } searchResponse = client.Scroll("1m", searchResponse.ScrollId); } client.ClearScroll(c => c.ScrollId(searchResponse.ScrollId)); // 91.8 seconds // unique question askers: 795352 Console.WriteLine($"unique question askers: {uniqueOwnerUserIds.Count}"); } 

术语聚合比Scroll API方法快约24倍。

上述就是C#学习教程:ElasticSearch Nest。 更好的术语聚合代码及其迭代分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/1006501.html

(0)
上一篇 2021年12月29日
下一篇 2021年12月29日

精彩推荐