【问题标题】:Why does this query cause 'too many clauses'?为什么此查询会导致“子句过多”?
【发布时间】:2020-12-04 00:28:29
【问题描述】:

我有一个只有几个“应该”和“过滤器”的查询,但其中一个过滤器有一个包含约 20,000 个词条的词条查询。我们的 max_terms_count 是 200k,但这是在抱怨“条款”。

原因:org.elasticsearch.ElasticsearchException:Elasticsearch 异常 [type=too_many_clauses,reason=too_many_clauses:maxClauseCount 设置为 1024]

我编写了包含术语查询的查询,其中的术语远多于此。为什么此查询会导致“子句过多”错误?如何重写此查询以获得相同的结果而不会出现错误?

{
    "query" : {
      "bool" : {
        "filter" : [
          {
            "nested" : {
              "query" : {
                "range" : {
                  "dateField" : {
                    "from" : "2019-12-03T21:34:30.653Z",
                    "to" : "2020-12-02T21:34:30.653Z",
                    "include_lower" : true,
                    "include_upper" : true,
                    "boost" : 1.0
                  }
                }
              },
              "path" : "observed_feeds",
              "ignore_unmapped" : false,
              "score_mode" : "none",
              "boost" : 1.0
            }
          }
        ],
        "should" : [
          {
            "bool" : {
              "filter" : [
                {
                  "terms" : {
                    "ipAddressField" : [
                      "123.123.123.123",
                      "124.124.124.124",
                      ... like 20,000 of these
                    ],
                    "boost" : 1.0
                  }
                }
              ],
              "adjust_pure_negative" : true,
              "boost" : 1.0
            }
          }
        ],
        "adjust_pure_negative" : true,
        "minimum_should_match" : "1",
        "boost" : 1.0
      }
    }
}

编辑:一个注释 - 我将术语查询包装在应该 -> bool 中的原因是因为有时我们需要将多个术语查询 OR'd 在一起。这恰好不是其中之一。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    您在使用术语查询时遇到此问题的原因是 should 子句在 filter 子句之外并有助于分数计算。这就是这些条款受 max_clause_count 约束的原因。如果该部分不需要分数,那么您可以将查询改写如下:

    {
      "query": {
        "bool": {
          "filter": [
            {
              "nested": {
                "query": {
                  "range": {
                    "dateField": {
                      "from": "2019-12-03T21:34:30.653Z",
                      "to": "2020-12-02T21:34:30.653Z",
                      "include_lower": true,
                      "include_upper": true,
                      "boost": 1
                    }
                  }
                },
                "path": "observed_feeds",
                "ignore_unmapped": false,
                "score_mode": "none",
                "boost": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "terms": {
                            "ipAddressField": [
                              "123.123.123.123",
                              "124.124.124.124",
                              ... like 20,000 of these
                            ],
                            "boost": 1
                          }
                        }
                      ],
                      "adjust_pure_negative": true,
                      "boost": 1
                    }
                  }
                ]
              }
            }
          ],
          "adjust_pure_negative": true,
          "boost": 1
        }
      }
    }
    

    【讨论】:

    • 这会导致“[应该]查询格式错误,查询名称后没有 start_object”。将 'should' 包裹在 bool 中可修复错误,但仍会出现最大子句错误
    • 我的错,错过了将should 子句包含在bool 中。修好了。
    • 对不起,我猜你看到后我编辑了我之前的评论。还是一样的 max 子句错误
    • 天啊。好的 - 我将我的示例简化了一点,这似乎有所作为。我会跟进一个更长的解释
    • 我的ipAddressField 实际上是一个带有ip 类型子字段的关键字字段。我正在尝试查询子字段。如果我将查询更改为针对主要关键字字段,则您的解决方案有效。我会改变我的问题以反映这一点。
    猜你喜欢
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2016-08-15
    • 2021-10-12
    • 2010-10-27
    • 1970-01-01
    相关资源
    最近更新 更多