【问题标题】:Elasticsearch group/aggregate respons by search criteriaElasticsearch 按搜索条件分组/聚合响应
【发布时间】:2021-01-19 03:58:51
【问题描述】:

我有一个具有 categoryIds 属性的产品。

"id" : 1,
"title" : "product",
"price" : "1100.00",
"categories" : [ the ids of the product's categories],
"tags" : [ the ids of the product's tags ],
"variants" : [ nested type with properties: name, definition, maybe in the future availability dates]

我想根据查询中的类别对产品 ID 进行分组。 在 POST _search 中,我询问属于特定类别的产品(例如 [1, 2, 3]),我还可以使用变体来限制它们。 如何对我的答案进行分组/聚合以获取某个类别的 productId 列表? 我想得到什么:

{
    "productsForCategories": {
        "1": [
            "product-1",
            "product-2",
            "product-3"
        ],
        "2": [
            "product-1",
            "product-3",
            "product-4"
        ],
        "3": [
            "product-5",
            "product-6"
        ]
    }
}

提前感谢所有答案。

java 生成了什么。

curl --location --request POST 'https://localhost:9200/products/_search' \
--header 'Content-Type: application/json' \
--data-raw '{
    "size": 0,
    "query": {
        "bool": {
            "must": [
                {
                    "bool": {
                        "should": [
                            {
                                "term": {
                                    "categories": {
                                        "value": 7,
                                        "boost": 1.0
                                    }
                                }
                            }
                        ],
                        "adjust_pure_negative": true,
                        "minimum_should_match": "1",
                        "boost": 1.0,
                        "_name": "fromRawQuery"
                    }
                }
            ],
            "filter": [
                {
                    "bool": {
                        "adjust_pure_negative": true,
                        "boost": 1.0,
                        "_name": "filterPart"
                    }
                }
            ],
            "adjust_pure_negative": true,
            "boost": 1.0,
            "_name": "queryPart"
        }
    },
    "_source": {
        "includes": [
            "categories",
            "productType",
            "relations"
        ],
        "excludes": []
    },
    "stored_fields": "_id",
    "sort": [
        {
            "_score": {
                "order": "desc"
            }
        }
    ],
    "aggregations": {
        "agg": {
            "global": {},
            "aggregations": {
                "categories": {
                    "terms": {
                        "field": "categories",
                        "size": 2147483647,
                        "min_doc_count": 1,
                        "shard_min_doc_count": 0,
                        "show_term_doc_count_error": false,
                        "order": [
                            {
                                "_count": "desc"
                            },
                            {
                                "_key": "asc"
                            }
                        ]
                    },
                    "aggregations": {
                        "productsForCategories": {
                            "terms": {
                                "field": "_id",
                                "size": 2147483647,
                                "min_doc_count": 1,
                                "shard_min_doc_count": 0,
                                "show_term_doc_count_error": false,
                                "order": [
                                    {
                                        "_count": "desc"
                                    },
                                    {
                                        "_key": "asc"
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        }
    }
}'```

【问题讨论】:

    标签: java elasticsearch elasticsearch-aggregation


    【解决方案1】:

    您可以使用terms aggregation,这是一种基于多桶值源的聚合,其中桶是动态构建的 - 每个唯一值一个。

    添加一个包含索引数据、映射、搜索查询和搜索结果的工作示例

    索引映射:

    {
      "mappings":{
        "properties":{
          "categories":{
            "type":"keyword"
          }
        }
      }
    }
    

    索引数据:

    {
      "id":1,
      "product":"p1",
      "category":[1,2,7]
    }
    {
      "id":2,
      "product":"p2",
      "category":[7,4,5]
    }
    {
      "id":3,
      "product":"p3",
      "category":[4,5,6]
    }    
    

    搜索查询:

        {
      "size": 0,
      "aggs": {
        "cats": {
          "terms": {
            "field": "cat_ids",
            "include": [
              7
            ]
          },
          "aggs": {
            "products": {
              "terms": {
                "field": "product.keyword",
                "size": 10
              }
            }
          }
        }
      }
    }
    

    搜索结果:

    "aggregations": {
        "cats": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": 7,
              "doc_count": 2,
              "products": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                  {
                    "key": "p1",
                    "doc_count": 1
                  },
                  {
                    "key": "p2",
                    "doc_count": 1
                  }
                ]
              }
            }
          ]
        }
    

    【讨论】:

    • @sicio 好久不见了。我希望你做得很好:) 你有没有机会通过我的回答,期待得到你的反馈:)
    【解决方案2】:

    我相信您想要的是与每个类别对应的产品。正如 Bhavya 提到的,您可以使用 term 聚合。

    GET products/_search
    {
      "size": 0, //<===== If you need only aggregated results, set this to 0. It represents query result size.
      "aggs": {
        "categories": {
          "terms": {
            "field": "cat_ids", // <================= Equivalent of group by Cat_ids
            "size": 10
          },"aggs": {
            "products": {
              "terms": {
                "field": "name.keyword",//<============= For Each category group by products
                "size": 10
              }
            }
          }
        }
      }
    }
    

    结果:

      "aggregations" : {
    "categories" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 1,       //<========== category id
          "doc_count" : 2, //<========== For the given category id 2 products
          "products" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "p1",  //<========= for cat_id=1, p1 is there
                "doc_count" : 1
              },
              {
                "key" : "p2", //<========= for cat_id=1, p2 is there
                "doc_count" : 1
              }
            ]
          }
        },
        {
          "key" : 2,
          "doc_count" : 2,
          "products" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "p1",
                "doc_count" : 1
              },
              {
                "key" : "p2",
                "doc_count" : 1
              }
            ]
          }
        },
        {
          "key" : 3,
          "doc_count" : 1,
          "products" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "p1",
                "doc_count" : 1
              }
            ]
          }
        }
      ]
    }
    

    }

    详细信息以 cmets 的形式显示。请移除 cmets 并尝试运行查询。


    过滤聚合结果: See this

    【讨论】:

    • 你的答案和我的答案有什么区别(除了你添加的 cmets)?
    • 您已经对产品进行了分组,然后按类别进行了分组,我相信这不是被问到的。 Ask是获取每个类别的产品。如果我错了,请纠正我,我将删除我多余的答案:)
    • @Bhavya:我很高兴删除我的答案。只需根据提出的问题更改您的答案即可。
    • @Sahil-gupta 聚合不包括查询。可以做点什么吗?
    • 你这是什么意思?顺便说一句,我没有在这里添加查询语法。您可以添加相同的内容。如果它回答了您的问题,请接受/投票
    猜你喜欢
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 2022-12-06
    • 2021-01-02
    • 2016-04-21
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    相关资源
    最近更新 更多