在前N个结果上的聚合

时间:2015-03-18 15:03:55

标签: elasticsearch

问题:

如果我搜索“iphone”,我会得到400个产品结果和产品类别聚合,我会返回结果集中的前3个类别。

这些类别包括智能手机,手机壳和手机配件。

如果我搜索“iphone 6”,我会得到1400个结果,因为额外的“6”返回匹配更多产品。产品类别聚合现在返回所有这些结果的前3个类别。

前3个产品类别现在将是从电缆到计算机显示器的所有产品。

我需要做的是获得前100名成绩的前3个类别。


我尝试了什么:

我尝试在顶级类别聚合中使用top_hits聚合,但只返回每个类别中的顶级产品。

这样的事情:

{
    "aggs": {

        "product_categories": {
            "terms": {
                "field": "product_category",
                "size": 10,
            }
        }        
        "aggs": {
            "top-categories": {
                "top_hits": {
                    "size" : 3
                }
            }
        }
    }
}

我还尝试创建一个带有子聚合的top_hits聚合来获取顶级类别,但这也不起作用。

{
    "aggs": {
        "top-categories": {
            "top_hits": {
                "size" : 100
            }
            "aggs": {
                "product_categories": {
                    "terms": {
                        "field": "product_category",
                        "size": 3,
                    }
                }
            }
        }
    }
}

任何人都可以帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:4)

您可以尝试使用基于filter过滤器的limit聚合,并将terms聚合嵌套在其中。

请注意,限制是在分片级<处应用(请参阅documentation)。

但是,这应该适合您的情况,使用如下查询:

{
  "aggs": {
    "limit_results": {
      "filter": {
        "limit": {
          "value": 100
        }
      },
      "aggs": {
        "product_categories": {
          "terms": {
            "field": "product_category",
            "size": 10
          }
        }
      }
    }
  }
}

答案 1 :(得分:2)

在开始之前,请注意这不是问题的完美解决方案。但是,它可以明确地缓解这种情况,在特殊情况下,它实际上是一个完美的解决方案。

我建议的解决方案是根据找到的文档的分数对聚合桶的术语进行排序。也就是说,术语的排序不再仅仅是频率,而是文档得分。

以下是一个示例请求:

{
   "query": {
       "query_string": {
           "default_field": "product_title",
           "query": "iphone 6"
       }
   },
   "aggs": {
       "product_categories": {
           "terms": {
               "field": "product_category",
               "order": {
                   "max_score": "desc",
                   "_count": "desc"
               },
               "size": 3
           },
           "aggs": {
               "max_score": {
                   "max": {
                       "script": "_score"
                   }
               }
           }
       }
   }
}

请注意&#34;命令&#34;聚合术语的属性。它指定max_score聚合的路径,该路径又返回特殊的_score字段,该字段处理查询的每个命中文档的分数。它也可以通过&#34; _count&#34;每次使用频率。第二个位置的财产。

此请求将为您提供product_category字段中最好的三个术语,这些术语非常频繁且来自高排名的文档&#34;。我不能更明确地说明排名是如何完成的。我在初步实验中注意到,结果并没有单调列举文档分数,但可能会跳过&#34;跳过&#34;一个排名很高的文档,它只包含低频率的术语 - 实际上可能是你想要的用例。这种排序的文档可在此处找到:http://www.elastic.co/guide/en/elasticsearch/reference/1.x/search-aggregations-bucket-terms-aggregation.html

上述链接文档中还有一个示例,用于按多个条件进行排序,并且只是说&#34;上面将根据女性人口中的平均高度对国家/地区进行排序,然后按降序排列doc_count&# 34 ;.我的印象是它可能是某种调和的意思或某种东西。也许更好地了解一下你是否觉得这种方法的结果很有用。

我在开头谈到的特殊情况是每个文档在请求的字段中只有一个值。在这种情况下,当你省略&#34; _count&#34;时,你实际上得到了前N个(因为N相等)文件的前N个术语。排序

答案 2 :(得分:2)

您正在寻找Sampler Aggregation。我在Aggregation on top n results

处有类似的答案
{
  "aggs": {
    "bestDocs": {
       "sampler": {
            "shard_size":100
         },
       "aggs": {
          "product_categories": {
             "terms": {
                "field": "product_category",
                "size": 3
             }
          }
       } 
   }
}

将按照分数对前100个文档进行排序,然后进行术语汇总。