首页 > 解决方案 > 查询与过滤器以及查询或过滤器中正确表达式的使用

问题描述

我在 SO 中看到了很多问题,并阅读了有关“过滤器被缓存”的文档,而查询没有被缓存,“查询应用于所有值”和“如果在查询对象之外,则在查询后应用过滤器”等.

底线是文档很烂,而且 DSL 很难掌握。我正在尝试优化一些查询并使用 kibana 开发工具搜索分析器,但是我的本地数据集必须太小而无法测量实际的性能差异(我在两个方向上都得到了结果)而且我没有测试具有多个节点的集群,用于处理真实的大型数据集。

在这种简单的情况下,所有查询都将返回相同的结果。我想了解其中的区别,以及为什么在任何允许将子句放在过滤器中的情况下,您更喜欢查询而不是过滤器

GET foo11/_search
{
  "query": {
    "bool": {
      "filter": {
        "match" : {
          "in_stock" : true
        }
      }
    }
  }
}

GET foo11/_search
{
  "query": {
    "bool": {
      "filter": {
        "term" : {
          "in_stock" : true
        }
      }
    }
  }
}


GET foo11/_search
{
  "query": {
    "bool": {
      "must": {
        "match" : {
          "in_stock" : true
        }
      }
    }
  }
}

这3种情况在性能上有什么区别?我真的可以证明一个比另一个更好/更差吗?

有什么区别:

"match" : {
  "in_stock" : true
}

对比

"term" : {
  "in_stock" : true
}

标签: elasticsearchluceneelasticsearch-dsl

解决方案


有几个不同的问题和概念需要解开。

比赛与学期

查询在索引中查找之前对您提供的搜索值match执行分析(删除常见的停用词、提取词干以删除尾随的“ing”、“es”等)。分析的目标是使意思大致相同的单词匹配,例如,如果您搜索“bananas”但您将“banana”编入索引,它仍然会找到它。值得注意的是,为了使分析工作在您索引数据时还必须在字段上进行,这就是textElasticsearch 中的类型字段所做的。

term查询是不执行任何分析的完全匹配。这更像是您在关系数据库中所习惯的。这些是针对keyword字段和其他数据类型字段(数字、布尔值、日期)执行的。如果您需要同时匹配两种方式,您可以使用这两种类型来索引该字段。

查询与过滤

elasticsearch 中的Aquery是一系列搜索子句,这些子句将根据它们的相关性相互评分和排名。换句话说,根据您让我搜索的词,哪些文档似乎最相关。

elasticsearch 中的Afilter限制了查询运行所针对的记录集,并且不执行评分。您可以将其视为在进行更昂贵的计算以确定搜索词与每个文档的相关性之前确定要检查哪些记录的第一遍。

您提到的另一个重要区别filters是缓存,但queries不是。通常,如果您想要应用广泛的条件,您可以制作这些过滤器,并将“人类文本”搜索部分设为查询。一般来说,如果您有广泛的限制,您可以限制可搜索的文档集,您可以将其放在过滤器中,以利用缓存和避免评分的时间节省。例如:仅过滤食谱中的产品,然后查询带有单词bananas 的标题。

性能测量

衡量查询性能可能很困难,因为其中有很多移动部件。如果您有时间,最好的方法是将有代表性的(并且有点大)数据量索引到单个节点,然后在向外扩展之前针对该数据进行初始测试。您可能还想查看 Elasticsearch 的性能测试工具,称为 Rally。

https://github.com/elastic/rally

把它们放在一起

对于上面的示例,由于您正在搜索的字段是布尔值,因此您希望进行term查询,而不是match查询。此外,您可以在filter子句中执行此操作,因为没有对单个布尔值进行相关性评分。如果您想将它与其他文本搜索结合起来,您可以在queryjson 正文的上下文中添加一个匹配子句。


推荐阅读