分面搜索的后过滤器和全局聚合之间有什么区别?

2024-04-27

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

这有时被称为“多面结果”,或者 “多面导航”。这Elasticsearch 参考中的示例 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-post-filter.html非常清楚地解释了为什么/如何,所以 我用它作为这个问题的基础。

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

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


选项 1:后置过滤器

see the Elasticsearch 参考中的示例 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-post-filter.html

我们能做的是在我们的原始查询中获得更多结果,这样我们就可以聚合这些结果,然后 过滤我们的实际结果。

这个例子解释的很清楚:

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

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

请参阅下面的示例代码,了解其外观。

这样做的一个问题是我们无法使用缓存。这是在(5.1 尚未提供)弹性搜索指南 https://www.elastic.co/guide/en/elasticsearch/guide/master/_post_filter.html警告:

性能考虑仅当您需要差异化过滤搜索结果和聚合时才使用 post_filter。有时人们会使用 post_filter 进行常规搜索。

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

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

然而,还有一个不同的选择:

选项 2:全局聚合

有一种方法可以进行不受搜索查询影响的聚合。 因此,我们不是得到很多,而是对其进行聚合,然后进行过滤,我们只是得到过滤后的结果,但对它们进行聚合 一切。看一看在参考处 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-global-aggregation.html

我们可以得到完全相同的结果。我没有读到任何关于缓存的警告,但看起来最后 我们需要做大约相同数量的工作。所以这可能是唯一的遗漏。

由于我们需要子聚合(你不能有global and a filter于 同一水平')。

我读到的关于使用此查询的唯一抱怨是,如果您需要这样做,您可能必须重复自己 对于几个项目。最后我们可以生成大多数查询,因此重复自己对于我的用例来说并不是什么问题, 我并不认为这是与“无法使用缓存”同等的问题。

Question

看起来这两个功能至少有重叠,或者可能提供完全相同的功能。这让我很困惑。 除此之外,我想知道其中一个是否有我没有看到的优势,以及这里是否有任何最佳实践?

Example

这很大程度上来自于后置过滤器参考页 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-post-filter.html,但我添加了全局过滤器 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-global-aggregation.html query.

地图和文件

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 项),我们为这 2 件衬衫提供的衬衫类型(修身版和普通版), 以及 gucci 有哪些颜色(红色和蓝色)。

首先,后置过滤器:获取所有衬衫,聚合红色 gucci 衬衫的型号和 gucci 衬衫的颜色(所有颜色), 红色 gucci 衬衫的后置过滤器仅显示结果:(这与示例有点不同,因为我们 尝试使其尽可能接近后置滤波器的清晰应用。)

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

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


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

From 这篇有弹性的博文 https://www.elastic.co/blog/found-optimizing-elasticsearch-searches我们得到了最初的提示:

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

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

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

事实证明,让它们并行运行要快得多。看一下多搜索API https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html#search-multi-search

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分面搜索的后过滤器和全局聚合之间有什么区别? 的相关文章

随机推荐

  • pandas 中的索引对象——为什么 pd.columns 返回索引而不是列表

    来自 R 背景 我发现 非常高 使用Indexpandas 中的对象有点令人不安 例如 如果train是一个pandas DataFrame 有什么特殊原因吗train columns应该返回一个Index而不是一个列表 如果它是一个Ind
  • 如何在 Android 上检测从 3g 到 H+ 的网络类型更改

    通过连接管理器和广播接收器 我能够获取连接和断开连接事件 如下所述埃里克的帖子在这里 https stackoverflow com questions 1783117 network listener android 我想知道的是网络连接
  • IntelliJ IDEA 在项目 jar 中查找类

    我看过一些关于通过在目录中搜索 jar 来查找类的帖子 这让我认为 IntelliJ IDEA 中一定有一个工具可以做到这一点 有人知道这样的工具以及如何使用它吗 如果 jar 文件作为项目依赖项导入 您可以键入cmd n然后搜索它
  • ROS中spin和rate.sleep的区别

    我是 ROS 新手 正在尝试了解这个强大的工具 我很困惑spin and rate sleep功能 谁能帮助我了解这两个功能之间的区别以及何时使用每个功能 ros spin and ros spinOnce 负责处理通信事件 例如到达的消息
  • Java EE / Jakarta EE 支持 Java 模块系统吗?是否可以使用Java模块系统制作Web应用程序?

    我正在使用 Java 11 和 Maven 3 6 1 构建我的第一个模块化应用程序 我的IDE是IntellijIDEA 2019 1 3 我添加了一个模块 app 并添加module info java 但我很困惑 因为即使我向应用程序
  • fork 和现有线程?

    在linux系统上 子进程查看现有线程的方式与父进程相同吗 int main create thread 1 int child pid fork if 0 child pid else 由于子进程复制了整个地址空间 因此线程的状态会发生什
  • 如何在节点中转义 shell 命令的字符串?

    In nodejs http nodejs org 执行外部命令的唯一方法是通过 sys exec cmd 我想调用外部命令并通过标准输入为其提供数据 在nodejs中 似乎还没有一种方法可以打开命令 然后将数据推送到它 仅执行并接收其标准
  • 查找游戏对象的子对象的子对象

    我在场景中有一个预制件 我想访问该预制件的子项 该预制件的结构如下 PauseMenu UI Resume TextField TextField2 UI Side Back lt I need this child UI Home tra
  • 如何 adb 提取 SD 卡中文件夹中的所有文件

    我的 SD 卡中有一个文件夹 mnt sdcard Folder1 Folder2 Folder3 jpg 文件夹 1 和文件夹 2 的名称保持不变 文件夹 2 内有文件夹 3 4 5 等 我想使用 adb 将所有 jpeg 文件而不是所有
  • 具有多个数据源的 Spring Boot + JNDI

    我尝试创建一个 Spring Boot 应用程序 它连接两个数据源 我能够通过遵循 Spring 文档来实现这一目标 但我面临的挑战是实现以下目标 通过使用 Spring Boot DataSourceAutoConfiguration 通
  • Baqend 中的关系和 ACL

    我试图弄清楚 baqend 是否可以做到这一点 或者甚至是正确的方法 我有很多用户 使用 Baqend 附带的默认用户帐户系统 其中一些用户将是公司的管理员 一家公司将拥有 1 到 5 名管理员用户 有一个单独的数据类 其中包含公司的记录和
  • 数据库连接未使用 jpaFlowExecutionListener 关闭

    我正在使用 Spring Web Flow 来构建应用程序 我正在利用Flow Managed Persistence Context因此实体管理器在流程执行期间保持打开状态 我可以访问延迟加载的属性 类似于OpenEntityManage
  • 创建 QT 应用程序作为 Windows 上现有基于控制台的应用程序的 GUI

    我正在尝试使用 Qt 为现有应用程序设置一个 GUI 该应用程序旨在在 Windows 命令行中运行 这不仅仅是运行应用程序system 命令 但我需要通过命令行与现有应用程序交互 The system 当我启动现有的可执行文件时 命令会阻
  • sql 查询不适用于 order by

    这是我原来有效的查询 Select FROM story st sentences s speaker sp WHERE st lesson id 1 AND st speaker id sp speaker id AND st sente
  • 是否有一个排序的java集合可以处理重复项?

    我需要一个行为类似于 C multimap 的集合 但我还需要能够通过一系列键获取元素 你可以看看谷歌收藏 http code google com p google collections 它有多种实现MultiMap
  • 泛型和实体框架:如何根据列值返回不同的类型

    我们有一个人员表 其中存储不同类型的人员 买方 卖方 代理人等 我们的 ORM 是实体框架 CodeFirst CTP5 我们使用存储库模式来实现良好的 TDD 和模拟 在 PersonRepository 中 我想返回特定类型 这样我就可
  • 如何为 64 位 Windows 编译现有的 posix 代码?

    我可以使用 Cygwin 或 MinGW 但我需要最终得到 64 位代码 而不是 32 位 这是因为我将从 64 位托管 C 调用 DLL 我似乎找不到关于设置这些工具来创建 64 位二进制文 件的良好参考 另外 如果 GCC 是版本 4
  • 将 jQuery 单击事件分配给正文中除少数 div 及其子元素之外的所有内容

    当我按下页面上的 div 时 会出现一个弹出窗口 当您再次单击该 div 时 弹出窗口就会消失 当您单击 div 外部时 弹出窗口就会消失 到目前为止一切看起来都很好 问题是 当我单击弹出窗口时 我希望弹出窗口及其子窗口可以单击 它们是无序
  • 在外语版本的 Excel 中从 vba 调用工作表函数

    以下代码片段在英语版本的 Excel 中运行正常 但是当尝试在葡萄牙语版本的 Excel 中的同一工作簿中运行此代码时 会出错 Add color bars on every other row attempt to make list e
  • 分面搜索的后过滤器和全局聚合之间有什么区别?

    搜索界面中的一个常见问题是您想要返回结果的选择 但可能想返回有关所有文档的信息 例如 我想查看所有红色衬衫 但想知道什么 其他颜色可供选择 这有时被称为 多面结果 或者 多面导航 这Elasticsearch 参考中的示例 https ww