在我们的一个新项目中,我们受到了这篇文章http://project-a.github.io/on-site-search-design-patterns-for-e-commerce/#generic-faceted-search的启发,因为它们是我们的“方面”结构。虽然我已经在文章描述的范围内使用它,但是在选择方面时我遇到了让它工作的问题。我希望有人能给出一些尝试的提示,所以我不必再将所有聚合重做为单独的聚合计算。
问题基本上是我们使用单个聚合一次计算所有“方面”,但是当我添加过滤器(fx。检查品牌名称)时,它会在返回时“删除”所有其他品牌聚合。我基本上想要的是它在计算其他方面时应该使用该品牌作为过滤器,但在计算品牌聚合时则不然。这是必要的,因此用户可以选择多个品牌。
看https://www.contorion.de/search/Metabo_Fein/ou1-ou2?q=Winkelschleifer&c=bovy(这是上面文章中描述的网站),我选择了“Metabo”和“Fein”制造商(Hersteller),展开了Hersteller菜单,它显示了所有制造商,而不仅仅是选中的。所以我知道它有可能以某种方式,我希望有一个关于如何编写聚合/过滤器的提示,所以我得到了“正确的电子商务方面行为”。
在ES中的产品上,我有以下结构:(与原始文章相同,但在命名时使用“C#”ified)
"attributeStrings": [
{
"facetName": "Property",
"facetValue": "Organic"
},
{
"facetName": "Property",
"facetValue": "Without parfume"
},
{
"facetName": "Brand",
"facetValue": "Adidas"
}
]
所以上面的产品有2个属性/方面组 - 具有2个值的属性(有机,没有香水)和带有1个值的品牌(阿迪达斯)。 没有任何过滤器,我会根据以下查询计算聚合:
"aggs": {
"agg_attr_strings_filter": {
"filter": {},
"aggs": {
"agg_attr_strings": {
"nested": {
"path": "attributeStrings"
},
"aggs": {
"attr_name": {
"terms": {
"field": "attributeStrings.facetName"
},
"aggs": {
"attr_value": {
"terms": {
"field": "attributeStrings.facetValue",
"size": 1000,
"order": [
{
"_term": "asc"
}
]
} } } } } } } }
现在,如果我选择Property“Organic”和Brand“Adidas”,我会构建相同的聚合,但是使用过滤器来应用这两个约束(这有点出错......):
"aggs": {
"agg_attr_strings_filter": {
"filter": {
"bool": {
"filter": [
{
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Property"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Organic"
]
}
}
]
}
},
"path": "attributeStrings"
}
},
{
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Brand"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Adidas"
]
}
}
]
}
},
"path": "attributeStrings"
}
}
]
}
},
"aggs": {
"agg_attr_strings": {
"nested": {
"path": "attributeStrings"
},
"aggs": {
"attr_name": {
"terms": {
"field": "attributeStrings.facetName",
},
"aggs": {
"attr_value": {
"terms": {
"field": "attributeStrings.facetValue",
"size": 1000,
"order": [
{
"_term": "asc"
}
]
} } } } } } } }
我能看到这个模型的唯一方法是计算每个选定方面的聚合,并以某种方式合并结果。但它似乎非常复杂,有点像文章中所描述的那样使模型失败,所以我希望有一个更清晰的解决方案,有人可以提供一些尝试。
答案 0 :(得分:16)
我能看到这个模型的唯一方法是计算每个选定方面的聚合,并以某种方式合并结果。
这是完全正确的。如果您选择了一个方面(例如品牌),那么如果您还想要获取其他品牌进行多选,则无法使用全球品牌过滤器。您可以执行的操作是在所选方面应用所有其他过滤器,在非选定方面应用所有 过滤器。作为结果,您将为n+1
个选定过滤器提供n
个单独的聚合 - 第一个用于所有方面,其余用于选定方面。
在您的情况下,查询可能如下所示:
{
"aggs": {
"agg_attr_strings_filter": {
"filter": {
"bool": {
"filter": [
{
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Property"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Organic"
]
}
}
]
}
},
"path": "attributeStrings"
}
},
{
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Brand"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Adidas"
]
}
}
]
}
},
"path": "attributeStrings"
}
}
]
}
},
"aggs": {
"agg_attr_strings": {
"nested": {
"path": "attributeStrings"
},
"aggs": {
"attr_name": {
"terms": {
"field": "attributeStrings.facetName"
},
"aggs": {
"attr_value": {
"terms": {
"field": "attributeStrings.facetValue",
"size": 1000,
"order": [
{
"_term": "asc"
}
]
}
}
}
}
}
}
}
},
"special_agg_property": {
"filter": {
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Brand"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Adidas"
]
}
}
]
}
},
"path": "attributeStrings"
}
},
"aggs": {
"special_agg_property": {
"nested": {
"path": "attributeStrings"
},
"aggs": {
"agg_filtered_special": {
"filter": {
"query": {
"match": {
"attributeStrings.facetName": "Property"
}
}
},
"aggs": {
"facet_value": {
"terms": {
"size": 1000,
"field": "attributeStrings.facetValue"
}
}
}
}
}
}
}
},
"special_agg_brand": {
"filter": {
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Property"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Organic"
]
}
}
]
}
},
"path": "attributeStrings"
}
},
"aggs": {
"special_agg_brand": {
"nested": {
"path": "attributeStrings"
},
"aggs": {
"agg_filtered_special": {
"filter": {
"query": {
"match": {
"attributeStrings.facetName": "Brand"
}
}
},
"aggs": {
"facet_value": {
"terms": {
"size": 1000,
"field": "attributeStrings.facetValue"
}
}
}
}
}
}
}
}
}
}
这个查询看起来超级大而可怕,但生成这样的查询可以用几十行代码完成。
解析查询结果时,需要首先解析一般聚合(使用所有过滤器的聚合)和特殊构面聚合之后。从上面的示例中,首先解析来自agg_attr_strings_filter
的结果,但这些结果还将包含 Brand 和 Property 的聚合值,这些聚合值应该由来自{{的聚合值覆盖1}}和special_agg_property
此外,此查询是有效的,因为Elasticsearch在缓存单独的过滤器子句方面做得很好,因此在查询的不同部分应用相同的过滤器应该很便宜。
但它看起来非常复杂,有点像文章中所描述的那样使模型失败,所以我希望有一个更清晰的解决方案,有人可以提供一些尝试。
实际上,您无需将不同的过滤器应用于不同的方面,同时具有不同的查询过滤器。如果您需要支持"纠正电子商务方面的行为"你将有复杂的查询:)
免责声明:我是上述文章的合着者。
答案 1 :(得分:5)
问题来自于您在聚合中添加Property
和Organic
过滤器的事实,因此您选择的方面越多,您就越能克制您将获得的条款。在该文章中,他们使用的filter
实际上是post_filter
,这两个名称直到最近才被允许,但filter
got removed因为这导致含糊不清。
您需要做的是将聚合外部的过滤器移动到post_filter
部分,以便通过拾取的任何方面正确滤除结果,但所有方面仍然可以在整个文件集。
{
"post_filter": {
"bool": {
"filter": [
{
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Property"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Organic"
]
}
}
]
}
},
"path": "attributeStrings"
}
},
{
"nested": {
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Brand"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Adidas"
]
}
}
]
}
},
"path": "attributeStrings"
}
}
]
}
},
"aggs": {
"agg_attr_strings_full": {
"nested": {
"path": "attributeStrings"
},
"aggs": {
"attr_name": {
"terms": {
"field": "attributeStrings.facetName"
},
"aggs": {
"attr_value": {
"terms": {
"field": "attributeStrings.facetValue",
"size": 1000,
"order": [
{
"_term": "asc"
}
]
}
}
}
}
}
},
"agg_attr_strings_filtered": {
"filter": {
"bool": {
"filter": [
{
"nested": {
"path": "attributeStrings",
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Property"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Organic"
]
}
}
]
}
}
}
},
{
"nested": {
"path": "attributeStrings",
"query": {
"bool": {
"filter": [
{
"term": {
"attributeStrings.facetName": {
"value": "Brand"
}
}
},
{
"terms": {
"attributeStrings.facetValue": [
"Adidas"
]
}
}
]
}
}
}
}
]
}
},
"aggs": {
"nested": {
"path": "attributeStrings"
},
"aggs": {
"attr_name": {
"terms": {
"field": "attributeStrings.facetName"
},
"aggs": {
"attr_value": {
"terms": {
"field": "attributeStrings.facetValue",
"size": 1000,
"order": [
{
"_term": "asc"
}
]
}
}
}
}
}
}
}
}
}
答案 2 :(得分:0)
我正在努力实现你们在这里讨论的内容。我也关注该线程中提到的文章,但是尝试了3个星期之后,我似乎无法弄清楚过滤器为何返回正确的结果,但是当我将过滤器放入聚合中时,聚合都是错误的。我已经用示例in this question详细介绍了整个过程,我想知道是否有人对我有任何帮助,以防我陷入困境。非常感谢!