【问题标题】:query vs filter and usage of correct expression in the query or filter查询与过滤器以及查询或过滤器中正确表达式的使用
【发布时间】:2018-11-15 05:13:26
【问题描述】:

我在 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
}

【问题讨论】:

    标签: elasticsearch lucene elasticsearch-dsl


    【解决方案1】:

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

    匹配与期限

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

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

    查询与过滤

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

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

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

    性能测量

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

    https://github.com/elastic/rally

    把它们放在一起

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

    【讨论】:

      【解决方案2】:

      第二个更快

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

      速度更快的原因: - 过滤器不会为您的文档评分。 - 术语将匹配确切的单词,跳过分析部分。

      更多参考: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html

      【讨论】:

        猜你喜欢
        • 2020-09-06
        • 1970-01-01
        • 2013-01-13
        • 1970-01-01
        • 2012-02-02
        • 2020-08-29
        • 2015-12-25
        • 1970-01-01
        • 2012-07-11
        相关资源
        最近更新 更多