gpt4 book ai didi

java - 如何创建文档子集并在 Elasticsearch 中对该子集执行查询?

转载 作者:行者123 更新时间:2023-11-30 02:16:06 25 4
gpt4 key购买 nike

原因是我们有一个 API,可以从客户端接收查询参数并构建 Elasticsearch 查询。然而,根据用户的类型(无论是财务顾问还是投资者等),我们必须应用更多条件来限制搜索。不幸的是,我们无法对索引的结构进行任何更改(即添加额外的列),这是因为索引不是由我们管理的,并且除了可配置的列名称之外,我们的 API 没有有关索引的信息。

所以这是一个例子。收到基于“investorDateOfBirth”和“financialAdviserId”的搜索请求,并且由于搜索来自顾问,因此我们以编程方式添加此条件:

financialAdviserId must be '123' (the id of the current user)

因此最终查询变为:

{
"bool" : {
"must" : [
{
"term" : {
"financialAdviserId" : {
"value" : "123",
"boost" : 1.0
}
}
}
],
"should" : [
{
"term" : {
"investorDateOfBirth" : {
"value" : "1987-11-12",
"boost" : 1.0
}
}
},
{
"term" : {
"financialAdviserId" : {
"value" : "123",
"boost" : 1.0
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}

如您所见,有 2 个“financialAdviserId”,一个是根据请求查询参数以编程方式构建的,另一个(“必须”)是根据当前用户添加的,但如您所知,这将返回那些具有指定的 investorDateOfBirth 以及顾问 id 为 123 的所有其他项目(包括那些没有相同出生日期的项目)

假设索引中有 3 条记录:

| investorDateOfBirth | financialAdviserId | investorId |
| "1987-11-12" | 123 | 111 |
| "1900-11-12" | 123 | 222 |
| "1900-11-12" | 123 | 333 |

对于上面的查询,结果是全部 3 行,这不是我们想要的结果,但是,对于以下查询,它返回仅第一行,这是期望的:

{
"bool" : {
"must" : [
{
"term" : {
"financialAdviserId" : {
"value" : "123",
"boost" : 1.0
}
}
}
],
"should" : [
{
"term" : {
"investorDateOfBirth" : {
"value" : "1987-11-12",
"boost" : 1.0
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}

如何解决这个问题?我们如何更改第一个查询以获得与第二个查询(返回第一行)相同的结果。

只是想让您知道,我们无法使 financialAdviserId 不可搜索,因为还有其他实体可以搜索这些列?有没有办法创建一个子集(在我们的例子中,financialAdviserId 为 123 的子集),然后针对该子集执行客户端请求的查询?

我们在 Java 8 中使用 Elasticsearch v5.5.3

最佳答案

你就快到了。为了获得预期的行为,您可以将一个 bool 嵌套到另一个中:

{
"bool": {
"must": [
{
"term": {
"financialAdviserId": {
"value": "123"
}
}
},
{
"bool": {
"should": [
{
"term": {
"investorDateOfBirth": {
"value": "1987-11-12"
}
}
},
{
"term": {
"financialAdviserId": {
"value": "123"
}
}
}
]
}
}
]
}

(我删除了 boost 和其他细节以使想法更加清晰。)

为什么问题中的第一个查询不起作用

现在让我解释为什么初始查询不起作用。

您在 bool 的同一个实例中使用了 mustshould询问。本例中记录的行为如下:

should

If the bool query is in a query context and has a must or filter clause then a document will match the bool query even if none of the should queries match.

(这也是为什么使用 Federico 中的 filter 的建议无法解决问题的原因。)

所以实际上您应用的查询具有以下逻辑含义:

    query_restricting_set_of_docs AND (user_query or True)

而您正在寻找这个:

    query_restricting_set_of_docs AND user_query

在您的情况下user_query看起来像这样:

    query_restricting_set_of_docs OR some_other_query

这给我们带来了最终的表达式:

    query_restricting_set_of_docs AND (
query_restricting_set_of_docs OR some_other_query
)

转换为 ES bool 查询,如下所示:

{
"bool": {
"must": [
{
...query_restricting_set_of_docs
},
{
"bool": {
"should": [
{
...query_restricting_set_of_docs
},
{
...other_query
}
]
}
}
]
}
}

注意 query and filter context

过滤器和查询上下文之间的主要区别是:

  • 查询上下文计算相关性分数,并且结果不会缓存
  • 过滤器上下文不计算分数,但结果会被缓存

缓存部分将使搜索速度更快,但如果没有相关性分数,您将无法首先显示更多相关文档。在您的情况下,您可能希望将 query_restricting_set_of_docs 放入过滤器上下文中。

为此,您可以使用以下查询:

{
"bool": {
"must": [
{
"bool": {
"filter": [
{
"term": {
"financialAdviserId": {
"value": "123"
}
}
}
]
}
},
{
"bool": {
"should": [
{
"term": {
"investorDateOfBirth": {
"value": "1987-11-12"
}
}
},
{
"term": {
"financialAdviserId": {
"value": "123"
}
}
}
]
}
}
]
}
}

这里我们用 filterquery_restricting_set_of_docs 包装到另一个 bool 中,从而实现过滤部分的过滤器上下文。

如果您可以控制索引并且您想要限制索引的几个不同子集,则可以使用 Filtered Aliases ,这基本上会将指定的过滤器添加到针对该别名执行的所有查询中。

希望有帮助!

关于java - 如何创建文档子集并在 Elasticsearch 中对该子集执行查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48372929/

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