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

分面搜索的后过滤器和全局聚合有何区别?

隆睿
2023-03-14
问题内容

搜索界面中的一个常见问题是您希望返回选择的结果,但可能希望返回有关所有文档的信息。(例如,我想看到所有的红色衬衫,但想知道还有哪些其他颜色可用)。

有时将其称为“分面结果”或“分面导航”。Elasticsearch参考资料中的示例非常清楚地说明了为什么/如何做,因此我将其用作该问题的基础。

摘要/问题:看来我可以同时使用后置过滤器或全局聚合。
它们似乎都以不同的方式提供了完全相同的功能。我可能看不到它们的优缺点?如果是这样,我应该使用哪个?

我在下面提供了一个完整的示例,其中包含一些文档和一个基于参考指南中示例的两种方法的查询。

选项1:后置过滤器

请参阅Elasticsearch参考中的示例

我们可以做的是在原始查询中获得更多结果,因此我们可以汇总这些结果,然后过滤实际结果。

该示例在解释它时非常清楚:

但也许您还想告诉用户有多少种其他颜色的Gucci衬衫可供选择。如果仅在颜色字段上添加术语聚合,则只会返回红色,因为查询仅返回Gucci的红色衬衫。

相反,您希望在聚合过程中包括所有颜色的衬衫,然后仅将颜色过滤器应用于搜索结果。

在下面的示例代码中查看其外观。

与此有关的一个问题是我们不能使用缓存。这是在(尚未适用于5.1的)elasticsearch指南中警告以下内容:

性能注意 事项仅在需要差异过滤搜索结果和聚合时,才使用post_filter。有时人们会使用post_filter进行常规搜索。

不要这样!post_filter的性质意味着它在查询之后运行,因此,过滤的任何性能优势(例如缓存)都将完全丧失。

post_filter仅应与聚合结合使用,并且仅在需要差分过滤时才使用。

但是,有另一种选择:

选项2:全局汇总

有一种方法可以进行不受搜索查询影响的聚合。因此,我们没有得到很多,而是对其进行汇总,然后进行过滤,而只是得到过滤后的结果,而是对所有内容进行汇总。看看参考

我们可以获得完全相同的结果。我没有读到任何有关缓存的警告,但最终似乎我们需要做同样数量的工作。因此,这也许是唯一的遗漏。

由于我们需要子聚合,所以它稍微复杂一点(您不能在相同的“级别”上拥有globalfilter)。

我唯一读到的有关使用此查询的投诉是,如果您需要对多个项目执行此操作,则可能不得不重复自己的操作。最后,我们可以生成大多数查询,因此对于我的用例而言,重复自己并不是什么大问题,并且我真的不认为这与“不能使用缓存”同等重要。

似乎两个功能至少是重叠的,或者可能提供完全相同的功能。这让我感到困惑。除此之外,我想知道一个或另一个是否具有我从未见过的优势,以及这里是否有最佳实践?

这主要来自后过滤器参考页,但是我添加了全局过滤器查询。

地图和文件

PUT /shirts
{
    "mappings": {
        "item": {
            "properties": {
                "brand": { "type": "keyword"},
                "color": { "type": "keyword"},
                "model": { "type": "keyword"}
            }
        }
    }
}

PUT /shirts/item/1?refresh
{
    "brand": "gucci",
    "color": "red",
    "model": "slim"
}

PUT /shirts/item/2?refresh
{
    "brand": "gucci",
    "color": "blue",
    "model": "slim"
}


PUT /shirts/item/3?refresh
{
    "brand": "gucci",
    "color": "red",
    "model": "normal"
}


PUT /shirts/item/4?refresh
{
    "brand": "gucci",
    "color": "blue",
    "model": "wide"
}


PUT /shirts/item/5?refresh
{
    "brand": "nike",
    "color": "blue",
    "model": "wide"
}

PUT /shirts/item/6?refresh
{
    "brand": "nike",
    "color": "red",
    "model": "wide"
}

现在,我们要求所有红色gucci衬衫(项目1和3),这两种衬衫的衬衫类型(苗条和普通)以及gucci的颜色(红色和蓝色)。

首先,进行后期过滤:获取所有衬衫,汇总红色gucci衬衫的模型和gucci衬衫的颜色(所有颜色),然后对红色gucci衬衫的后期过滤器仅显示结果:(这与以下结果略有不同:该示例,因为我们试图使它尽可能接近possilbe的后过滤器的清晰应用。)

GET /shirts/_search
{
  "aggs": {
    "colors_query": {
      "filter": {
        "term": {
          "brand": "gucci"
        }
      },
      "aggs": {
        "colors": {
          "terms": {
            "field": "color"
          }
        }
      }
    },
    "color_red": {
      "filter": {
        "bool": {
          "filter": [
            {
              "term": {
                "color": "red"
              }
            },
            {
              "term": {
                "brand": "gucci"
              }
            }
          ]
        }
      },
      "aggs": {
        "models": {
          "terms": {
            "field": "model"
          }
        }
      }
    }
  },
  "post_filter": {
    "bool": {
      "filter": [
        {
          "term": {
            "color": "red"
          }
        },
        {
          "term": {
            "brand": "gucci"
          }
        }
      ]
    }
  }
}

我们还可以获取所有红色gucci衬衫(我们的原始查询),然后对模型(对于所有gucci衬衫)和颜色(对于所有gucci衬衫)进行全局汇总。

GET /shirts/_search
{
  "query": {
    "bool": {
      "filter": [
        { "term": { "color": "red"   }},
        { "term": { "brand": "gucci" }}
      ]
    }
  },
  "aggregations": {
    "color_red": {
      "global": {},
      "aggs": {
        "sub_color_red": {
          "filter": {
            "bool": {
              "filter": [
                { "term": { "color": "red"   }},
                { "term": { "brand": "gucci" }}
              ]
            }
          },
          "aggs": {
            "keywords": {
              "terms": {
                "field": "model"
              }
            }
          }
        }
      }
    },
    "colors": {
      "global": {},
      "aggs": {
        "sub_colors": {
          "filter": {
            "bool": {
              "filter": [
                { "term": { "brand": "gucci" }}
              ]
            }
          },
          "aggs": {
            "keywords": {
              "terms": {
                "field": "color"
              }
            }
          }
        }
      }
    }
  }
}

两者都将返回相同的信息,第二个仅因子聚合引入的额外级别而有所不同。第二个查询看起来有点复杂,但是我认为这不是很大的问题。现实世界中的查询是由代码生成的,无论如何可能都更复杂,它应该是一个好的查询,如果这意味着复杂的话,那就这样吧。


问题答案:

我们使用的实际解决方案虽然不能直接回答问题,但基本上是“都不可行”。

从这个富有弹性的博客文章中,我们得到了最初的提示:

有时,我看到搜索过于复杂,其目标是在尽可能少的搜索请求中进行尽可能多的操作。它们倾向于尽可能晚地使用过滤器,这完全与“过滤器优先”中的建议相反。不要害怕使用多个搜索请求来满足您的信息需求。多重搜索API可让您发送一批搜索请求。

不要将所有内容都塞进单个搜索请求中。

这基本上就是我们在上面的查询中所做的:一大堆聚合和一些过滤。

让它们并行运行被证明要快得多。看看多重搜寻API



 类似资料:
  • 问题内容: 我要实现的目标:我不希望查询过滤器过滤“年龄”聚合,并且希望能够对其应用过滤器。 因此,如果我从以下查询开始: 我的聚合“ young_age”将同时被filter_1和filter_2过滤。我不希望我的汇总被filter_1过滤。 在查看文档时,我认为全局聚合可以解决我的问题,因此我编写了以下查询: 但是然后elasticsearch抱怨我的filter_2: “”“在[global

  • 如何在elasticsearch中使用与聚合相关的过滤器? 官方文档只给出了过滤器和聚合的小例子,没有对查询dsl进行正式描述——例如,将其与postgres文档进行比较。 通过尝试,我发现以下查询被elasticsearch接受(没有解析错误),但忽略了给定的过滤器: 有些人建议使用查询而不是过滤。但官方文件通常建议对精确值进行过滤。查询的另一个问题是:虽然过滤器提供了和,但查询不提供。 有人能

  • 问题内容: 如何在$ lookup之后添加过滤器,或者有其他方法可以执行此操作? 我的数据收集测试是: 我选择ID 100并汇总孩子: 我回来了: 但我只希望与“值:1”匹配的子项 最后,我希望得到以下结果: 问题答案: 这里的问题实际上是关于一些不同的东西,根本不需要。但是,对于仅从“$lookup之后过滤”标题到达此处的任何人,这些都是适合您的技术: MongoDB 3.6-子管道 较早-$

  • 我试图使用过滤器聚合来支持前端的多选择方面值。 我有颜色和深度滤镜。 滤色器保存值:黑色(5)、蓝色(3)、红色(2) 深度过滤器保持值:70mm(3)、60mm(5)、50mm(3) 当我在滤色器中选择黑色时,所有其他选项(蓝色,红色)都没有响应。 我尝试添加 谢了,Sree。

  • 轻推的全局搜索,可输入关键字来搜索联系人、群聊、组织机构、文件、聊天记录、文章、订阅号、轻应用。搜索出的聊天记录还可以查看聊天内容上下文。 1.手机版 搜索方法:消息/通讯录上方搜索栏-输入关键词   2.电脑版:左上方搜索栏-输入关键词

  • exVim使用ex-gsearch进行全局搜索。它也在必要 时候和id-utils创建的管道协同工作。总之,当你使用:Update后,exVim将会生成被 ex-gsearch使用的ID文件。 *注意事项: * 如果不能搜索,首先看你这个ID文件是否已经生成! 查找文本 ex-gsearch有俩个主要的方式可以在你的工程中 搜索文本。 <leader>gg: 将会搜索光标下的单词。 :GS <wo