elasticsearch - Elasticsearch Nest Top Hits 聚合

标签 elasticsearch nest

我已经为一个问题苦苦挣扎了一段时间,所以我想我可以通过 stackoverflow 解决这个问题。

我的文档类型有一个标题、一个语言字段(用于过滤)和一个分组 ID 字段(我省略了所有其他字段以保持这一点)

当我搜索文档时,我想找到所有包含标题中文本的文档。每个唯一的分组 ID 只需要一个文档。

我一直在研究 tophits 聚合,据我所知,它应该能够解决我的问题。

针对我的索引运行此查询时:

{
  "query": {
    "match": {
      "title": "dingo"
    }
  },
  "aggs": {
    "top-tags": {
      "terms": {
        "field": "groupId",
        "size": 1000000
      },
      "aggs": {
        "top_tag_hits": {
          "top_hits": {
            "_source": {
              "include": [
                "*"
              ]
            },
            "size": 1
          }
        }
      }
    }
  }
}

我得到以下响应(所有结果都使用相同的语言):

{
    "took": 9,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 3,
        "max_score": 0,
        "hits": []
    },
    "aggregations": {
        "top-tags": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [{
                "key": "3044BC9E7C29450AAB2E4B6C9B35AAE2",
                "doc_count": 2,
                "top_tag_hits": {
                    "hits": {
                        "total": 2,
                        "max_score": 1.4983996,
                        "hits": [{
                            "_index": "elasticsearch",
                            "_type": "productdocument",
                            "_id": "FB15279FB18E4B34AD66ACAF69B96E9E",
                            "_score": 1.4983996,
                            "_source": {
                                "groupId": "3044BC9E7C29450AAB2E4B6C9B35AAE2",
                                "title": "wombat, dingo and zetapunga actionfigures",

                            }
                        }]
                    }
                }
            },
            {
                "key": "F11799ABD0C14B98ADF2554C84FF0DA0",
                "doc_count": 1,
                "top_tag_hits": {
                    "hits": {
                        "total": 1,
                        "max_score": 1.30684,
                        "hits": [{
                            "_index": "elasticsearch",
                            "_type": "productdocument",
                            "_id": "42562A25E4434A0091DE0C79A3E7F3F4",
                            "_score": 1.30684,
                            "_source": {
                                "groupId": "F11799ABD0C14B98ADF2554C84FF0DA0",
                                "title": "awesome dingo raptor"
                            }
                        }]
                    }
                }
            }]
        }
    }
}

这正是我所期望的(一个桶中有两次命中,但该桶只检索到一个文档)。但是,当我在 NEST 中尝试此操作时,我似乎无法检索所有文档。

我的查询是这样的:

result = _elasticClient.Search<T>(s => s
                .From(skip)
                .Filter(fd => fd.Term(f => f.Language, language))
                .Size(pageSize)
                .SearchType(SearchType.Count)
                .Query(
                    q => q.Wildcard(f => f.Title, query, 2.0)
                         || q.Wildcard(f => f.Description, query)
                )
                .Aggregations(agd =>
                    agd.Terms("groupId", tagd => tagd
                        .Field("groupId")
                        .Size(100000) //We sadly need all products
                    )
                    .TopHits("top_tag_hits", thagd => thagd
                        .Size(1)
                        .Source(ssd => ssd.Include("*")))
                ));

var topHits = result.Aggs.TopHits("top_tag_hits");
var documents = topHits.Documents<ProductDocument>(); //contains only one document (I would expect it to contain two, one for each bucket)

在调试器中检查聚合显示有一个包含 2 个桶的“groupId”聚合(并将我在“原始”查询中看到的内容与索引相匹配。只是没有任何明显的方法来检索文档)

所以我的问题是。我如何检索每个桶的最高命中率?还是我这样做完全错了?有没有其他方法可以实现我想要做的事情?

编辑

在我得到帮助后,我能够通过以下方式检索我的结果:

result = _elasticClient.Search<T>(s => s
                .From(skip)
                .Filter(fd => fd.Term(f => f.Language, language))
                .Size(pageSize)
                .SearchType(SearchType.Count)
                .Query(
                    q => q.Wildcard(f => f.Title, query, 2.0)
                         || q.Wildcard(f => f.Description, query)
                )
                .Aggregations(agd =>
                    agd.Terms("groupId", tagd => tagd
                        .Field("groupId")
                        .Size(0)
                    .Aggregations(tagdaggs =>
                        tagdaggs.TopHits("top_tag_hits", thagd => thagd
                            .Size(1)))
                    )
                )
                );

                var groupIdAggregation = result.Aggs.Terms("groupId");

                var topHits =
                    groupIdAggregation.Items.Select(key => key.TopHits("top_tag_hits"))
                        .SelectMany(topHitMetric => topHitMetric.Documents<ProductDocument>()).ToList();

最佳答案

您的 NEST 查询尝试同时运行 Terms 聚合和 TopHits,而您的原始查询首先运行 Terms,然后为每个存储桶调用 TopHits。

您只需将 TopHits 聚合移动到 NEST 查询中的 Terms 中即可使其正常工作。

这应该可以解决:

.Aggregations(agd =>
    agd.Terms("groupId", tagd => tagd
        .Field("groupId")
        .Size(0)
        .Aggregations(tagdaggs =>
            tagdaggs.TopHits("top_tag_hits", thagd => thagd
                .Size(1)))
    )
)

顺便说一下,您不必使用 Include("*") 来包含所有字段。只需删除此选项,同时指定 .Size(0) 即可为您返回所有可能的术语。

关于elasticsearch - Elasticsearch Nest Top Hits 聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33994818/

相关文章:

search - 如何使用minimum_should_match 进行多字段搜索?

elasticsearch - Elasticsearch低于现有领域

c# - 如何使用ElasticSearch(C#/NEST)搜索多个索引?

elasticsearch - Elasticsearch NEST客户端兼容性

c# - 查询返回两个文档而不是一个文档

c# - Elastic Search 术语查询未给出结果,但匹配查询给出

elasticsearch - Elasticsearch客户端NEST不存储时间戳

r - Elasticsearch返回一个字段

c# - NET Core中与ElasticSearch的集成问题Nlog

elasticsearch - Elasticsearch无法在Ubuntu 20.04中启动服务