当前位置: 首页 > 面试题库 >

Elasticsearch-通用构面结构-计算与过滤器组合的聚合

宿景曜
2023-03-14
问题内容

在我们的一个新项目中,我们受本文http://project-a.github.io/on-site-search-design-patterns-
for-e-commerce/#generic-faceted-search的
启发而做“构面”结构。虽然在本文所述的范围内可以使它正常工作,但是在选择构面时却遇到了使其无法工作的问题。我希望有人可以提示您尝试一下,所以我不必再次将所有聚合重做为单独的聚合计算。

问题基本上是,我们使用一次聚合来一次计算所有“方面”,但是当我添加一个过滤器(例如检查品牌名称)时,返回聚合时它会“移除”所有其他品牌。我基本上想要的是在计算其他方面时应使用该品牌作为过滤器,而在计算品牌汇总时则不应该使用该品牌。这是必要的,因此用户可以选择多个品牌。

查看https://www.contorion.de/search/Metabo_Fein/ou1-ou2?q=Winkelschleifer&c=bovy(上面文章中描述的网站),我选择了“
Metabo”和“ Fein”制造商(
Hersteller),然后展开Hersteller菜单,它会显示所有制造商,而不仅仅是选定的制造商。因此,我知道这是有可能的,我希望那里的某个人对如何编写聚合/过滤器有所提示,以便获得“正确的电子商务方面行为”。

在ES中的产品上,我具有以下结构:(与原始文章中的相同,尽管命名中为“ C#”化)

"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"
                      }
                    ]
   } } } } } } } }

现在,如果我选择属性“有机”和品牌“阿迪达斯”,我将建立相同的聚合,但是要应用这两个约束条件的过滤器(确实有点不对劲…):

  "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"
                      }
                    ]
   } } } } } } } }

我可以用此模型向前看的唯一方法是计算每个选定方面的聚合并以某种方式合并结果。但是,这似乎非常复杂并且有点像文章中描述的那样具有模型的要点,因此我希望有一个更简洁的解决方案,并且有人可以提供一些尝试的提示。


问题答案:

我可以用此模型向前看的唯一方法是计算每个选定方面的聚合并以某种方式合并结果。

这是完全正确的。如果选择了一个构面(例如 brand ),则如果您还想获取其他品牌进行多选,则无法使用全局品牌过滤器。您可以做的是将所有 其他
过滤器应用于选定的方面,并将 所有 过滤器
应用于未选定的方面。结果,您将为选定的过滤器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,但这些结果也将包含聚集值的
品牌财产 应该由聚集值覆盖special_agg_property,并special_agg_brand
另外,这个查询是有效的,因为Elasticsearch确实做好缓存单独的过滤条款,从而适用相同的筛选器在不同部分的查询应该便宜。

但是,这似乎非常复杂并且有点像文章中描述的那样具有模型的要点,因此我希望有一个更简洁的解决方案,并且有人可以提供一些尝试的提示。

实际上,您实际上无法将不同的过滤器应用于不同的方面,同时拥有不同的查询过滤器。如果您需要支持“正确的电子商务方面行为”,您将拥有复杂的查询:)

免责声明 :我是上述文章的合著者。



 类似资料:
  • 问题内容: 我正在尝试对数组中的值进行聚合,并且还过滤由前缀返回的存储桶。不知道这是否可行,或者我滥用过滤桶。 3份文件: 目的是获取带有字母B开头颜色的文档数量: 不幸的是,返回的结果包括Red。显然是因为带有红色的文档仍然按过滤器匹配,因为它们也具有蓝色和/或黑色。 有没有一种方法可以只过滤存储桶结果? 问题答案: 尝试此操作,它将过滤为存储桶本身创建的值:

  • 问题内容: 我想过滤出字段“ A”等于“ a”的文档,并且我想同时考虑字段“ A”,当然不包括先前的过滤器。我知道您可以将过滤器“置于查询之外”,以便在不应用该过滤器的情况下获得构面,例如: elasticsearch 单反 这非常好,但是如果我有多个滤镜和构面,每个滤镜和构面应该互相排斥,会发生什么?例: 也就是说,对于方面AI,希望保留除A:a以外的所有过滤器,对于方面B希望保留除B:b以外的

  • 不知道如何表达这个问题。我正在使用Elasticsearch 2.2。 让我们从数据集的一个示例开始,该数据集由5个文档组成: 被调用的\u实体始终具有uuid。coverage\u实体可以为空,也可以具有uuid。 我使用脚本在任何一个被调用的\实体上进行聚合。uuid或coverage\u实体。uuid: 现在,聚合已经从任一头生成了术语。调用了\u实体。uuid或标头。coverage\u实

  • 我有一个返回一组文档(100)的查询。我想对这些应用一个聚合,因为这些是最相关的。当我尝试聚合时,它返回所有结果的聚合,而不是前100个结果的聚合。

  • 我从事elasticsearch,我尝试混合两个工作查询。第一个是“and filter”,第二个是“bool filter”,但我失败了。 我的查询是从用户交互界面动态生成的。 “和过滤器”: 我需要“和过滤器”来查询数据,例如,字段必须等于“非洲”或“亚洲”或为空。这是一个工作查询的示例: 此查询工作正常,结果如下: 现在我需要用字段“D\u TYPESTATUS”来限制结果数据,该字段必须与

  • 以下是数据集的快照: 我想获得员工名单以及employeeStatus和employeeAddr。 所以我在employeeId上使用术语聚合,然后使用employeeStatus和employeeAddr的子聚合来获得这些详细信息。下面的查询正确返回结果。 现在我只想要永久身份的员工。所以我正在应用过滤器聚合。 现在的问题是雇员地址聚合没有为雇员地址返回存储桶,因为记录2在聚合完成之前就被过滤掉