【问题标题】:A better approach to exclude large list of items in Elasticsearch在 Elasticsearch 中排除大量项目的更好方法
【发布时间】:2021-04-15 19:01:56
【问题描述】:

我使用terms query 排除100,000 或更多项目的列表,因为terms query 默认只允许65,536 个terms,ES 抛出以下错误:

术语查询请求中使用的术语 [115687] 数量已超过允许的最大值 [65536]。可以通过更改 [index.max_terms_count] 索引级别设置来设置此最大值。

解决我的问题的一种方法是增加 ma​​x_terms_count,但我怀疑它会很慢。

另一种解决方案是在 PHP 中排除那些也太耗费资源的项目。

有没有更好的方法从 ES 搜索结果中排除大量项目?

【问题讨论】:

    标签: php elasticsearch


    【解决方案1】:
    1. 对于极少数情况,我建议使用面向客户端的解决方案:将异常列表分成两部分:前 65k 项应由 ES 处理,其余的 - 在 PHP 中。
    2. 面向性能的解决方案:将排除列表限制为 65k(客户端限制)

    【讨论】:

    • 谢谢!我会尝试你的第一个建议。
    【解决方案2】:

    我找到了解决方案,希望对可能面临同样问题的人有所帮助。 解决方案是将大列表拆分为多个较小的列表,并将每个列表放在单独的“术语”查询中。 例如,假设 ma​​x_terms_count 为 4,我们有 12 个项目需要从搜索结果中排除。

    $iMaxTermsCount = 4;
    
    $arItems = [
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
    ];
    
    if (count($arItems) <= $iMaxTermsCount) {
        // Add all items to the terms query. It will produce:
        // "terms": {
        //  "item_id": [
        //      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
        //  ]
        // }
    } else {
        $arChunks = array_chunk($arItems, $iMaxTermsCount);
    
        foreach ($arChunks as $ar) {
            // Add some (4) items to the terms query.
        }
    
        // The loop above will produce:
        // {
        //  "terms": {
        //      "item_id": [
        //          1, 2, 3, 4
        //      ]
        //  }
        // },
        // {
        //  "terms": {
        //      "item_id": [
        //          5, 6, 7, 8
        //      ]
        //  }
        // },
        // {
        //  "terms": {
        //      "item_id": [
        //          9, 10, 11, 12
        //      ]
        //  }
        // }
    }
    

    最终的 JSON 对象会是这样的:

    {
        "query": {
            "bool": {
                "must_not": [
                    {
                        "bool": {
                            "should": [
                                {
                                    "terms": {
                                        "item_id": [
                                            1, 2, 3, 4
                                        ]
                                    }
                                },
                                {
                                    "terms": {
                                        "item_id": [
                                            5, 6, 7, 8
                                        ]
                                    }
                                },
                                {
                                    "terms": {
                                        "item_id": [
                                            9, 10, 11, 12
                                        ]
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
    

    上面的查询将排除所有项目而不会引发任何错误。

    【讨论】:

      猜你喜欢
      • 2017-09-26
      • 1970-01-01
      • 2020-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 2015-04-11
      • 2021-01-03
      相关资源
      最近更新 更多