我对 ES 还很陌生,并且一直在尝试以与大多数大型电子商务商店相同的方式实现分面导航。
我的部分产品映射如下所示:
'name' => [
'type' => 'string',
'analyzer' => 'english_analyzer',
],
'range' => [
'type' => 'string',
'analyzer' => 'english_analyzer',
],
'filters' => [
'type' => 'nested',
'properties' => [
'name' => [
'type' => 'string',
'index' => 'not_analyzed',
],
'values' => [
'type' => 'object',
'properties' => [
'name' => [
'type' => 'string',
'index' => 'not_analyzed',
]
]
]
]
],
如您所见,我将分面作为嵌套对象存储在“过滤器”中。
在我的搜索查询中,我可以将此聚合添加到我的查询中:
'aggs' => [
'facets' => [
'nested' => ['path' => 'filters'],
'aggs' => [
'filters' => [
'terms' => [
'field' => 'filters.name', //facet group name
'size' => 0
],
'aggs' => [
'id' => [
'terms' => [
'field' => 'filters.id' //facet group ID
]
],
'values' => [
'terms' => [
'field' => 'filters.values.name', //facet name
'size' => 0
],
'aggs' => [
'id' => [
'terms' => [
'field' => 'filters.values.id' //facet id
]
]
]
]
]
]
]
]
]
这给了我一个很好的方面列表来坚持我的导航。我可以通过 2 种方式将选定的方面应用于我的文档结果:使用“后过滤器”或“过滤查询”
后过滤器在查询后应用聚合,因此无论用户选择了哪些方面,都会给我文档计数。相比之下,过滤后的查询会根据选定的分面计算分面计数,但它会隐藏没有匹配文档的分面。
我需要做的 - 以及大多数大型电子商务商店所做的 - 是两者的混合体。我希望方面计数基于所选内容,但忽略同一组中的任何方面。
如果我有这些方面:
颜色:
- 红色 (1)
- 蓝色 (2)
- 绿色 (3)
品牌:
- 奥迪 (1)
- 福特 (2)
- 宝马 (3)
如果有人选择蓝色,红色和绿色的计数应该保持不变,但会影响品牌的计数。
我在 Stack Overflow 上发现了一个类似的问题: ElasticSearch 聚合:每个聚合排除一个过滤器
据我所知,我需要提供一个预定义的方面列表(来自我的关系数据库)并将它们添加到我的聚合中。所以我有一个我的方面组的手动列表,然后我为每个组添加一个过滤器桶 ( https://www.elastic.co/guide/en/elasticsearch/guide/current/_filter_bucket.html )。在过滤器中,我需要添加一个布尔查询,其中包含我为每个方面组包含的所有用户选择的方面,而忽略属于该组的任何方面。
所以现在我有一个庞大的聚合列表,按它们的方面组分组/存储,每个都有一个过滤器,其中包含一个可能有十几个选定字段的布尔查询。现在的查询太大了,如果我把它贴在这里,可能一页都放不下!
考虑到我之前必须做的几乎是我需要的,这对我来说似乎是对我的查询的一个疯狂补充。这是我能做到这一点的唯一方法吗?
非常感谢任何帮助,我希望我的问题足够清楚。