【问题标题】:Group by multiple fields using Nest使用 Nest 按多个字段分组
【发布时间】:2021-04-28 06:19:03
【问题描述】:

鉴于我有以下数据:

| Date | Value |Count|
| 2021-01-01 | X | 1 |
| 2021-01-01 | X | 2 |
| 2021-01-01 | Y | 1 |
| 2021-02-02 | X | 1 |
| 2021-02-02 | X | 2 |
| 2021-02-02 | Y | 5 |

我想使用多个字段按这些数据分组。 (日期和值)。

   Example :  Data.GroupBy(x=> new { x.Date, x.Value });

预期结果:

| Date | Value | Count |
| 2021-01-01 | X | 3 |
| 2021-01-01 | Y | 1 |
| 2021-02-02 | X | 3 |
| 2021-02-02 | Y | 5 |

如何使用 Nest 执行此查询?

更新:

索引映射:

{
  "samples" : {
    "mappings" : {
      "properties" : {
        "count" : {
          "type" : "long"
        },
        "date" : {
          "type" : "date"
        },
        "value" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

【问题讨论】:

  • 您通过Nest 添加索引或在Kibana 仪表板中明确添加?因为当通过Nest 添加时,您可以将NumberOfShards 设置为索引。
  • 我使用 Nest 添加了索引
  • 很难猜测发生了什么。您可以在弹性连接上使用EnableDebugMode 来查看究竟是什么问题,您可以在异常中看到调试消息。
  • 我启用了调试模式,消息是:文本字段未针对需要按文档字段数据的操作(如聚合和排序)进行优化,因此默认情况下禁用这些操作。请改用关键字字段。我在使用 Suffix('keyword') 之前解决了这个问题,但我不知道脚本查询中 Suffix('keyword') 的等价物是什么。

标签: c# elasticsearch nest


【解决方案1】:

一个月前我也有同样的问题,假设你的班级是这样的:

 public class Sample
  {
    public string Date { get; set; }

    public string Value { get; set; }

    public int Count { get; set; }
  }

而最终的结果是这样的:

 public class Report
  {
    public string Date { get; set; }

    public string Value { get; set; }

    public double? SumCount { get; set; }
  }

然后在 elastic 上搜索:

public async Task<List<Report>> GetReportAsync(CancellationToken token)
        {
            var result = await _elasticClient.SearchAsync<Sample>(search => search
                .Aggregations(agg => agg
                    .Terms("result", t => t
                        .Script(sc => sc.Source("doc['date'].value+'#'+doc['value'].value").Lang(ScriptLang.Painless))
                        .Aggregations(a => a
                            .Sum("SumCount", s => s.Field(f => f.Count))
                        )))
                .Source(false)
                .Size(0), token);

            return result.Aggregations.Terms("result").Buckets.Select(x => new Report
            {
                Date = x.Key.Split(new[] { "#" }, StringSplitOptions.RemoveEmptyEntries)[0],
                Value = x.Key.Split(new[] { "#" }, StringSplitOptions.RemoveEmptyEntries)[1],
                SumCount = ((ValueAggregate)x["SumCount"])?.Value
            }).ToList();
        }

【讨论】:

  • 查询返回 400 BadRequest 错误:请求执行失败。调用:状态码 400 来自:POST /samples/_search?typed_keys=true。 ServerError:类型:search_phase_execution_exception 原因:“所有分片失败”
  • @ArsalanValoojerdi Cloud,您分享了如何将数据添加到 Elastic 中?错误在于您如何定义索引以及如何将模型映射到弹性。
  • 我在问题中添加了索引映射。
  • 我修复了将 doc['value'].value 更改为 doc['value.keyword'].value 的问题。谢谢
【解决方案2】:

在 Elasticsearch 6.1 及以后的版本中,Composite aggregation 是正确的选择

private static void Main()
{
    var default_index = "tmp";
    var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
    var settings = new ConnectionSettings(pool)
        .DefaultIndex(default_index);
        
    var client = new ElasticClient(settings);

    if (client.Indices.Exists(default_index).Exists)
        client.Indices.Delete(default_index);
    
    client.Indices.Create(default_index, c => c
        .Map<Tmp>(m => m
            .AutoMap()
        )
    );

    client.IndexMany(new [] 
    {
        new Tmp("2021-01-01", "X", 1),
        new Tmp("2021-01-01", "X", 2),
        new Tmp("2021-01-01", "Y", 1),
        new Tmp("2021-02-02", "X", 1),
        new Tmp("2021-02-02", "X", 2),
        new Tmp("2021-02-02", "Y", 5)
    });

    client.Indices.Refresh(default_index);

    var searchResponse = client.Search<Tmp>(s => s
        .Size(0)
        .Aggregations(a => a
            .Composite("composite", t => t
                .Sources(so => so
                    .DateHistogram("date", d => d.Field(f => f.Date).FixedInterval("1d").Format("yyyy-MM-dd"))
                    .Terms("value", t => t.Field(f => f.Value))
                )
                .Aggregations(aa => aa
                    .Sum("composite_count", su => su
                        .Field(f => f.Count)
                    )   
                )
            )
        )
    );
    
    Console.WriteLine("| Date | Value | Count |");
    foreach (var bucket in searchResponse.Aggregations.Composite("composite").Buckets)
    {
        bucket.Key.TryGetValue("date", out string date);
        bucket.Key.TryGetValue("value", out string value);
        var sum = bucket.Sum("composite_count").Value;
        Console.WriteLine($"| {date} | {value} | {sum} |"); 
    }
}

public class Tmp 
{
    public Tmp(string date, string value, int count)
    {
        Date = DateTime.Parse(date);
        Value = value;
        Count = count;
    }
    
    public Tmp()
    {
    }
    
    public DateTime Date {get;set;}
    
    [Keyword]
    public string Value {get;set;}
    public int Count {get;set;}
}

打印

| Date | Value | Count |
| 2021-01-01 | X | 3 |
| 2021-01-01 | Y | 1 |
| 2021-02-02 | X | 3 |
| 2021-02-02 | Y | 5 |

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-28
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多