gpt4 book ai didi

Elasticsearch - 寻找带有 id 的 must_not 的高性能方式

转载 作者:行者123 更新时间:2023-12-02 22:16:35 26 4
gpt4 key购买 nike

我有以下情况:

我们目前通过商业解决方案实现了产品搜索。
我正在使用 Elasticsearch 来实现我们当前使用 Elasticsearch 进行的产品搜索,基本上效果很好。
但我们有一个专长。我们有大约 100 万种产品的产品目录,但并不是每个客户都可以购买每一种产品。
有许多规则定义了客户是否可以购买产品。

这不仅仅是:

客户 A 不得购买供应商 A 的产品

或者:

客户 B 不得购买供应商 B 的 B 类产品。

那很容易。

为了获得这些不允许客户购买的产品,我们几年前实现了微服务/网络服务。这个网络服务返回一个产品黑名单,只是一个产品编号列表。

这样做的问题是,如果我只是在 Elasticsearch 中运行查询而忽略这些列入黑名单的产品,我会返回不允许客户购买的产品。如果我只查询前 10 个搜索结果,可能会发生这种情况,即我不允许展示这些产品,因为不允许客户购买它们。
此外,如果我使用供应商和类别的聚合,我会返回供应商和/或客户可能不允许购买的类别。

我在原型(prototype)中做了什么?

在查询 Elasticsearch 之前,我请求了某个客户的产品黑名单(当然还有缓存)。收到黑名单后,我运行如下查询:

{
"query" : {
"bool" : {
"must_not" : [
{
"ids" : {
"values" : [

// Numbers of blacklisted products. Can be thousands!

1234567,
1234568,
1234569,
1234570,
...
]
}
}
],
"should" : [
{
"query" : {
...
}
]
}
}
}
"aggregations" : {
...
}
}

这非常有效,但我们的客户拥有数千种列入黑名单的产品。因此,一方面我担心网络流量会太高,并且我意识到完整的 Elasticsearch 请求非常慢。但这基本上取决于黑名单产品的数量。

我的下一个方法 是开发我自己的 Elasticsearch 查询构建器作为插件,它处理 Elasticsearch 内部的黑名单内容。
此黑名单查询扩展了 AbstractQueryBuilder 并使用 TermInSetQuery。因此,此查询构建器请求给定客户的黑名单一次,将其缓存,并使用所有列入黑名单的产品编号构建一个 TermInSetQuery。

现在我的查询如下所示:
{
"query" : {
"bool" : {
"must_not" : [
{
"blacklist" : { <-- This is my own query builder
"customer" : 1234567
}
}
],
"should" : [
{
"query" : {
...
}
]
}
}
}
"aggregations" : {
...
}
}

这种解决方案速度更快,并且不必每次都在查询中发送整个列入黑名单的产品编号列表。所以我没有网络开销。但是查询仍然比没有这个黑名单的东西慢得多。我分析了这个查询,我并不惊讶地看到,我的黑名单查询占用了大约 80-90% 的运行时间。

我认为这个 TermInSetQuery 在我的情况下表现非常糟糕。因为我猜 Elasticsearch 各自的 Lucene 匹配过程不仅仅是一个:
if (blacklistSet.contains(id)) {
continue; // ignore the current search hit.
}

你们中有人对我有什么提示吗,如何更高效地实现这样的黑名单机制?

有没有办法拦截 Elasticsearch/Lucene 查询过程?
也许我可以编写自己的真实 Lucene 查询,而不是使用 TermInSetQuery。

提前致谢。

基督教

最佳答案

这不是解决方案,但可能是另一种方法。

首先,here是您可能感兴趣的较旧的 SO 帖子。据我所知,最新版本的 Elasticsearch 并没有引入/改变更好或更合适的东西。

如果您点击 Terms Query Documentation 的答案链接页面,你会发现一个非常简单的例子。

现在,您可以创建一个索引并为每个客户存储黑名单,而不是缓存您的黑名单。然后,您可以使用术语查询,并基本上从其他索引(=您的黑名单缓存)中引用黑名单。

我不知道这些黑名单的更新频率,所以这可能是个问题。此外,您必须小心不要不同步。特别值得一提的是,索引插入/更新默认情况下不会立即可见。因此,您可能需要在索引/更新黑名单时强制刷新。

正如我所说,这可能不是一个解决方案。但是,如果这对您来说听起来可行,那么可能值得尝试与您的其他解决方案进行比较。

关于Elasticsearch - 寻找带有 id 的 must_not 的高性能方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45372096/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com