【问题标题】:Elasticsearch correct aggregations for faceted searchElasticsearch 为分面搜索正确聚合
【发布时间】:2016-02-16 20:15:12
【问题描述】:

我想在某个平台上提供服装产品的分面搜索。因为我已经有了基于 Elasticsearch 的搜索功能(简单的查询,只有产品的名称),用 ES 实现分面搜索也很好。

这应该通过聚合来完成,因为分面已被弃用,并且也可以有嵌套聚合。

但是,我无法理解数以百万计的聚合以及哪些最适合我 - 有 termsfilterfiltersnestedchildren 等等。而且它们看起来都很合适。

我想要实现的目标可能听起来很基本:我有不同的方面(品牌、状况、颜色),每个方面都有不同的价值。对于某些方面(品牌),用户只能选择一个值。对于其他(颜色),用户最多可以选择 3 种(因为有些衣服有不止一种颜色)。


我从多字段术语方面开始。现在下一个自然步骤是将其转换为术语聚合(原因如上所述),但术语聚合不支持多字段。

{
    "query" : {
        "match_all" : {  }
    },
    "facets" : {
        "groupByBrandAndCondition" : {
            "terms" : {
                "fields" : ["brand", "condition"],
                "size" : 10
            }
        }
    }
}

我不知何故错过了一些关于如何进行并行多级分桶的简单但关键的点。用 UI 术语来说,用户应该能够选择以下内容:

  • 品牌 (10)
    • 一(7)
    • B (3) [X]
  • 颜色 (5)
    • 蓝色 (3) [X]
    • 红色 (2) [X]

读取:选择 A (7)、蓝色 (3)红色 (2)

【问题讨论】:

    标签: search elasticsearch facet faceted-search


    【解决方案1】:

    我创建了这样的基本映射

    POST your_index/your_type/_mapping
    {
      "your_type": {
        "properties": {
          "product": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "color": {
            "type": "string"
          }
        }
      }
    }
    

    我插入了一些这样的文档

    PUT your_index/your_type/111
    {
      "product" : "jeans" ,"brand" : "lee", "color" : "blue"
    }
    
    PUT your_index/your_type/1111
    {
      "product" : "shoes" ,"brand" : "levi", "color" : "black"
    }
    
    And so on
    

    这样的简单聚合查询

    GET your_index/_search
    {
      "size": 0,
      "aggs": {
        "prod_agg": {
          "terms": {
            "field": "product"
          },
          "aggs": {
            "brand_agg": {
              "terms": {
                "field": "brand"
              },
              "aggs": {
                "color_agg": {
                  "terms": {
                    "field": "color"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    将重新运行

    "aggregations": {
          "prod_agg": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
                {
                   "key": "shoes",
                   "doc_count": 4,
                   "brand_agg": {
                      "doc_count_error_upper_bound": 0,
                      "sum_other_doc_count": 0,
                      "buckets": [
                         {
                            "key": "nike",
                            "doc_count": 3,
                            "color_agg": {
                               "doc_count_error_upper_bound": 0,
                               "sum_other_doc_count": 0,
                               "buckets": [
                                  {
                                     "key": "blue",
                                     "doc_count": 2
                                  },
                                  {
                                     "key": "black",
                                     "doc_count": 1
                                  }
                               ]
                            }
                         },
                         {
                            "key": "levi",
                            "doc_count": 1,
                            "color_agg": {
                               "doc_count_error_upper_bound": 0,
                               "sum_other_doc_count": 0,
                               "buckets": [
                                  {
                                     "key": "black",
                                     "doc_count": 1
                                  }
                               ]
                            }
                         }
                      ]
                   }
                },
                {
                   "key": "jeans",
                   "doc_count": 3,
                   "brand_agg": {
                      "doc_count_error_upper_bound": 0,
                      "sum_other_doc_count": 0,
                      "buckets": [
                         {
                            "key": "lee",
                            "doc_count": 2,
                            "color_agg": {
                               "doc_count_error_upper_bound": 0,
                               "sum_other_doc_count": 0,
                               "buckets": [
                                  {
                                     "key": "black",
                                     "doc_count": 1
                                  },
                                  {
                                     "key": "blue",
                                     "doc_count": 1
                                  }
                               ]
                            }
                         },
                         {
                            "key": "levi",
                            "doc_count": 1,
                            "color_agg": {
                               "doc_count_error_upper_bound": 0,
                               "sum_other_doc_count": 0,
                               "buckets": [
                                  {
                                     "key": "black",
                                     "doc_count": 1
                                  }
                               ]
                            }
                         }
                      ]
                   }
                }
             ]
          }
       }
    

    这可用于填充 UI 搜索条件。

    那么如果用户想搜索鞋子,你可以查询

    GET your_index/_search
    {
      "size": 0,
      "query": {
        "match": {
          "product": "shoes"
        }
      }, 
      "aggs": {
        "brand_agg": {
          "terms": {
            "field": "brand"
          },
          "aggs": {
            "color_agg": {
              "terms": {
                "field": "color"
              }
            }
          }
        }
      }
    }
    

    这会给你

    "aggregations": {
          "brand_agg": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
                {
                   "key": "nike",
                   "doc_count": 3,
                   "color_agg": {
                      "doc_count_error_upper_bound": 0,
                      "sum_other_doc_count": 0,
                      "buckets": [
                         {
                            "key": "blue",
                            "doc_count": 2
                         },
                         {
                            "key": "black",
                            "doc_count": 1
                         }
                      ]
                   }
                },
                {
                   "key": "levi",
                   "doc_count": 1,
                   "color_agg": {
                      "doc_count_error_upper_bound": 0,
                      "sum_other_doc_count": 0,
                      "buckets": [
                         {
                            "key": "black",
                            "doc_count": 1
                         }
                      ]
                   }
                }
             ]
          }
       }
    

    或者您可以将它们作为单独的存储桶进行查询,例如

    GET your_index/_search
    {
      "size": 0,
      "query": {
        "match": {
          "product": "shoes"
        }
      },
      "aggs": {
        "brand_agg": {
          "terms": {
            "field": "brand"
          }
        },
        "color_agg" : {
          "terms": {
            "field": "color"
          }
        }
      }
    }
    

    这会给你

    "aggregations": {
          "color_agg": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
                {
                   "key": "black",
                   "doc_count": 2
                },
                {
                   "key": "blue",
                   "doc_count": 2
                }
             ]
          },
          "brand_agg": {
             "doc_count_error_upper_bound": 0,
             "sum_other_doc_count": 0,
             "buckets": [
                {
                   "key": "nike",
                   "doc_count": 3
                },
                {
                   "key": "levi",
                   "doc_count": 1
                }
             ]
          }
       }
    

    使用doc_count 值告诉用户他们有多少选项。

    这是否满足您的要求?

    【讨论】:

    • 感谢您的宝贵时间。我想说的是,带有单独存储桶的最后一部分是我问题末尾的样本列表。我仍然不太了解的是如何获取用户输入(比如选择颜色“蓝色”和“红色”)以及为其他字段提供存储桶。我是不是想多了 - 它只是搜索查询 + 聚合的组合吗?
    • 从你发布的问题来看,我觉得查询+聚合应该可以满足你的大部分需求。
    猜你喜欢
    • 2016-04-21
    • 2015-10-21
    • 2020-11-06
    • 2014-06-08
    • 2021-01-19
    • 2017-12-11
    • 2020-10-30
    • 2019-08-18
    • 2020-02-06
    相关资源
    最近更新 更多