【问题标题】:C# Nest & Elasticsearch 6.x : How to filter/count nested fields (in inner List<object>)C# Nest & Elasticsearch 6.x:如何过滤/计算嵌套字段(在内部 List<object> 中)
【发布时间】:2018-05-23 14:56:19
【问题描述】:

这是我的地图

[ElasticsearchType(Name = "Topic")]
public class Topic
{
    [Number(NumberType.Integer, Coerce = true)]
    public EnumStatus Status { get; set; }

    [Nested]
    public List<KeywordValue> KeywordValues { get; set; }

}

[ElasticsearchType(Name = "KeywordValue")]
public class KeywordValue
{
    [Keyword]
    public string KeywordId { get; set; }

}

我在索引中有 10 个 Topic 类型的文档,每个 KeywordValues 类型的 List&lt;KeywordValue&gt; 属性/字段包含 5 个 KeywordValue(列表中的 5 个元素)。

9 个文档的状态为“Enabled”;

我正在尝试计算每个嵌套 KeywordValues 字段中的元素总数。返回的结果是 9 但我想得到 45 (9*5)

我正在这样做:

var response = Topic.CurrentConnection.Search<Topic>(s => s
                .Size(0)
                .Aggregations(fa => fa
                    .Filter("filtered_aggs", f => f
                        .Filter(fd => fd.Term(t => t.Status, Topic.EnumStatus.Enabled))
                        .Aggregations(ta => ta
                                .Nested("kv", n=>n.Path(p => p.KeywordValues)
                                    .Aggregations(aa => aa
                                        .ValueCount("vc", v => v.Field(vf => vf.KeywordValues.First().KeywordId))))
                            )
                        )
                    )
            );


        if (response.IsValid)
        {
            var agg = response.Aggregations.Nested("filtered_aggs");
            var n = agg.Nested("kv");
            var z = n.ValueCount("vc");
            result.Object = z.Value;
        }

原始查询等效项:

# Request:
{
  "size": 0,
  "aggs": {
    "filtered_aggs": {
      "filter": {
        "term": {
          "Status": {
            "value": 0
          }
        }
      },
      "aggs": {
        "kv": {
          "nested": {
            "path": "KeywordValues"
          },
          "aggs": {
            "vc": {
              "value_count": {
                "field": "KeywordValues.KeywordId"
              }
            }
          }
        }
      }
    }
  }
}
# Response:
{
  "took" : 80,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 10,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "filter#filtered_aggs" : {
      "doc_count" : 9,
      "nested#kv" : {
        "doc_count" : 9,
        "value_count#vc" : {
          "value" : 9
        }
      }
    }
  }
}

有什么想法吗?非常感谢。

【问题讨论】:

  • 我已经阅读了这篇文章:stackoverflow.com/questions/39485196/… 以及关于 reverse_nested 的问题。我成功获得了 45 个结果,但是当我添加“过滤器”时,它不再起作用了 :(
  • 如果我这样做有什么好奇怪的:` var response = Topic.CurrentConnection.Search(s => s .Size(0) .Aggregations(fa => fa .Nested( "kv", n => n.Path(p => p.KeywordValues) ) ) ); ` 我得到了想要的结果。但如果我添加“过滤器”部分,则不是。
  • 如何将过滤器添加为bool 查询filter 子句在query 中,而不是过滤器聚合?
  • 谢谢@RussCam 我更新了查询/布尔然后聚合名为“kv”,你是对的,它更好但我得到了相同的结果。 9 而不是 45。:(

标签: c# elasticsearch nest elasticsearch-6


【解决方案1】:

这是一个工作示例

private static void Main()
{
    var defaultIndex = "topics";
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    var settings = new ConnectionSettings(pool)
        .DefaultIndex(defaultIndex);

    var client = new ElasticClient(settings);

    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);

    client.CreateIndex(defaultIndex, c => c
        .Mappings(m => m
            .Map<Topic>(mm => mm
                .AutoMap()
            )
        )
    );

    var documents = Enumerable.Range(1, 10)
        .Select(i => new Topic
        {
            Status = i == 1 ? EnumStatus.Disabled : EnumStatus.Enabled,
            KeywordValues = Enumerable.Range(1, 5)
                .Select(j => new KeywordValue
                {
                    KeywordId = $"keyword {i} {j}"
                }).ToList()
        });

    client.Bulk(b => b
        .IndexMany(documents, (d, document) => d
            .Document(document)
        )
        .Refresh(Refresh.WaitFor)
    );

    client.Search<Topic>(s => s
        .Size(0)
        .Query(q => +q
            .Term(t => t.Status, (int)EnumStatus.Enabled)
        )
        .Aggregations(ta => ta
            .Nested("kv", n => n.Path(p => p.KeywordValues)
                .Aggregations(aa => aa
                    .ValueCount("vc", v => v.Field(vf => vf.KeywordValues.First().KeywordId))))
        )
    );
}

[ElasticsearchType(Name = "Topic")]
public class Topic
{
    [Number(NumberType.Integer, Coerce = true)]
    public EnumStatus Status { get; set; }

    [Nested]
    public List<KeywordValue> KeywordValues { get; set; }

}

[ElasticsearchType(Name = "KeywordValue")]
public class KeywordValue
{
    [Keyword]
    public string KeywordId { get; set; }
}

public enum EnumStatus
{
    Enabled,

    Disabled
}

对搜索请求的响应是

{
  "took" : 9,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 9,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "nested#kv" : {
      "doc_count" : 45,
      "value_count#vc" : {
        "value" : 45
      }
    }
  }
}

【讨论】:

  • 非常感谢拉斯。这对我不起作用(我的意思是,我仍然得到 9 个计数而不是 45 个),也许我有一个映射问题。我会调查并回到这个线程......
  • 听起来像是与映射相关的@David。您通常无法更改现有映射,因此如果您已经有映射,最好使用新映射创建一个新索引并在那里尝试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多