【问题标题】:How to do sub-aggregations on nested objects with Elastic?如何使用 Elastic 对嵌套对象进行子聚合?
【发布时间】:2020-09-01 23:33:39
【问题描述】:

我有以下架构来表示可以有多个变体的产品(例如:T 恤的尺码):

{
    "mappings": {
        "properties": {
            "id": {"type": "keyword"},
            "name": {"type": "text"},
            "variants": {
                "type": "nested",
                "properties": {
                    "inventory": {"type": "long"},
                    "customizations": {"type": "object"},
                    "customizations.name": {"type": "keyword"},
                    "customizations.value": {"type": "keyword"}
                }
            }
        }
    }
}

然后我可以使用它插入如下所示的产品数据:

{
    "id": "prod-1",
    "name": "Shirt Design 1",
    "variants": [
        {"inventory": 78, "customizations": [{"name": "size", "value": "L"}, {"name": "color", "value": "blue"}]},
        {"inventory": 78, "customizations": [{"name": "size", "value": "M"}, {"name": "color", "value": "blue"}]},
        {"inventory": 89, "customizations": [{"name": "size", "value": "S"}, {"name": "color", "value": "blue"}]}
    ]
}
{
    "id": "prod-2",
    "name": "Shirt Design 2",
    "variants": [
        {"inventory": 78, "customizations": [{"name": "size", "value": "L"}, {"name": "color", "value": "green"}]},
        {"inventory": 78, "customizations": [{"name": "size", "value": "M"}, {"name": "color", "value": "green"}]}
    ]
}

在过滤/查询此索引时,我希望能够根据构成产品的自定义项来显示方面。这些自定义是用户提交的,因此不在我的控制范围内,但我们的想法是能够显示如下过滤器:

☐ Size:
    - S (1)
    - M (2)
    - L (2)
☐ Color:
    - blue (1)
    - green (1)

现在我可以使用以下查询按自定义名称正确存储桶:

{
    "size": 0,
    "aggs": {
        "skus": {
            "nested": {
                "path": "variants"
            },
            "aggs": {
                "customization_names": {
                    "terms": {
                        "field": "variants.customizations.name"
                    }
                }
            }
        }
    }
}

这给了我以下桶:

"buckets": [
        {
            "doc_count": 2,
            "key": "color"
        },
        {
            "doc_count": 2,
            "key": "size"
        }
    ],

尝试进行子聚合以获取下面的实际自定义列表是我卡住的地方。我试过了:

{
    "size": 0,
    "aggs": {
        "skus": {
            "nested": {
                "path": "variants"
            },
            "aggs": {
                "customization_names": {
                    "terms": {
                        "field": "variants.customizations.name"
                    },
                    "aggs": {
                        "sub": {
                            "reverse_nested": {},
                            "aggs": {
                                "customization_values": {
                                    "terms": {
                                        "field": "variants.customizations.value"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

不返回任何子存储桶:

buckets": [
                    {
                        "doc_count": 4,
                        "key": "color",
                        "sub": {
                            "doc_count": 2,
                            "customization_values": {
                                "buckets": [],
                                "doc_count_error_upper_bound": 0,
                                "sum_other_doc_count": 0
                            }
                        }
                    },
                    {
                        "doc_count": 4,
                        "key": "size",
                        "sub": {
                            "doc_count": 2,
                            "customization_values": {
                                "buckets": [],
                                "doc_count_error_upper_bound": 0,
                                "sum_other_doc_count": 0
                            }
                        }
                    }
                ],

如果我不使用reverse_nested,而不是空子存储桶,我会在其中获得所有可能的值,因此我会得到red and blue 作为size 子存储桶的一部分。

我最初将 customizations 作为 key => 值的映射,但也无法使其工作。但是,“自定义”的格式在这里有些可自定义。

到目前为止,我发现解决此问题的唯一方法是向自定义项添加一个字段,该字段是名称 + 值的 json 字符串表示形式。

// mapping:
"customizations.facet_code": {"type": "keyword"}
// data:
"customizations": [{"name": "size", "value": "M", "facet_code": "{name:size,value:M}"],

然后我可以根据facet_code 正确存储桶,我的应用程序可以反序列化它以再次将事物重新组合在一起。 如果可能的话,我希望我能弄清楚如何“正确”地做到这一点。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    执行此操作的“正确”方法是将customizations 也设为nested 类型,而不是object。也就是说:

    {
      "mappings": {
        "properties": {
          "id": {
            "type": "keyword"
          },
          "name": {
            "type": "text"
          },
          "variants": {
            "type": "nested",
            "properties": {
              "inventory": {
                "type": "long"
              },
              "customizations": {
                "type": "nested",       <-- This
                "properties": {
                  "name": {
                    "type": "keyword"
                  },
                  "value": {
                    "type": "keyword"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    查询将是

    {
      "size": 0,
      "aggs": {
        "skus": {
          "nested": {
            "path": "variants.customizations"
          },
          "aggs": {
            "customization_names": {
              "terms": {
                "field": "variants.customizations.name"
              },
              "aggs": {
                "customization_values": {
                  "terms": {
                    "field": "variants.customizations.value"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    产生所有需要的方面:

    {
      ...
      "aggregations":{
        "skus":{
          "doc_count":10,
          "customization_names":{
            "doc_count_error_upper_bound":0,
            "sum_other_doc_count":0,
            "buckets":[
              {
                "key":"color",
                "doc_count":5,
                "customization_values":{
                  "doc_count_error_upper_bound":0,
                  "sum_other_doc_count":0,
                  "buckets":[
                    {
                      "key":"blue",
                      "doc_count":3
                    },
                    {
                      "key":"green",
                      "doc_count":2
                    }
                  ]
                }
              },
              {
                "key":"size",
                "doc_count":5,
                "customization_values":{
                  "doc_count_error_upper_bound":0,
                  "sum_other_doc_count":0,
                  "buckets":[
                    {
                      "key":"L",
                      "doc_count":2
                    },
                    {
                      "key":"M",
                      "doc_count":2
                    },
                    {
                      "key":"S",
                      "doc_count":1
                    }
                  ]
                }
              }
            ]
          }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-29
      • 2016-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 2022-01-22
      相关资源
      最近更新 更多