在 Elasticsearch 中排除大量项目的更好方法

Sal*_*mov 6 php elasticsearch

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

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

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

另一种解决方案是在 PHP 中排除那些资源消耗过多的项目。

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

Sal*_*mov 0

我找到了解决方案,希望对那些可能面临同样问题的人有所帮助。解决方案是将大列表拆分为多个较小的列表,并将每个列表放入单独的“术语”查询中。例如,假设 max_terms_count4,并且我们需要从搜索结果中排除 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
    //      ]
    //  }
    // }
}
Run Code Online (Sandbox Code Playgroud)

最终的 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
                                    ]
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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