当前位置: 首页 > 知识库问答 >
问题:

如何嵌套bool查询?

长孙修远
2023-03-14

我正在构建一个搜索查询,它将一组约束(bool)动态地添加到查询中。一般预期结构如下

OR (

AND (
    condition
    condition
    ...
)

AND (
    condition
    condition
    ...
)

)

换句话说,我有一组(一个或多个)必须全部满足的条件(上面的)。可能有几个这样的集合,其中任何一个都足以进行最后的匹配(上面的)。

这种结构的一个示例,由我的代码生成(这是完整的API查询,生成的部分是“bool”):

{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "must": [
              {
                "term": {
                  "attack_ip": "10.89.7.117"
                }
              },
              {
                "term": {
                  "sentinel_port": "17"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "attack_ip": "10.89.7.118"
                }
              }
            ]
          }
        }
      ]
    },
    "range": {
      "eventtime": {
        "gte": "2018-03-05T12:47:22.397+01:00"
      }
    }
  },
  "size": 0,
  "aggs": {
    "src": {
      "terms": {
        "field": "attack_ip",
        "size": 1000
      },
      "aggs": {
        "dst": {
          "terms": {
            "field": "sentinel_hostname_lan",
            "size": 2000
          }
        }
      }
    }
  }
}

我对这个查询的理解是:

  • 如果“attack_ip===10.89.7.117”“sentinel_port===17”
  • 如果“attack_ip===10.89.7.118”

条目将匹配

不幸的是,我把Elasticsearch称为错误

"error": {
    "root_cause": [
      {
        "type": "parsing_exception",
        "reason": "[bool] malformed query, expected [END_OBJECT] but found [FIELD_NAME]",
        "line": 1,
        "col": 177
      }
    ],
    "type": "parsing_exception",
    "reason": "[bool] malformed query, expected [END_OBJECT] but found [FIELD_NAME]",
    "line": 1,
    "col": 177
  },
  "status": 400
}

这个错误是什么意思?

按照Piotr的回答,我尝试将range约束移到布尔部分。不过,我也犯了同样的错误。

我的查询可以在网上获得,以便于阅读,并转载如下:

{
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "should": [
              {
                "bool": {
                  "must": [
                    {
                      "term": {
                        "attack_ip": "10.89.7.117"
                      }
                    },
                    {
                      "term": {
                        "sentinel_port": "17"
                      }
                    }
                  ]
                }
              },
              {
                "bool": {
                  "must": [
                    {
                      "term": {
                        "attack_ip": "10.89.7.118"
                      }
                    }
                  ]
                }
              }
            ]
          }
        },
        {
          "range": {
            "eventtime": {
              "gte": "2018-03-05T13:55:27.927+01:00"
            }
          }
        }
      ]
    },
    "size": 0,
    "aggs": {
      "src": {
        "terms": {
          "field": "attack_ip",
          "size": 1000
        },
        "aggs": {
          "dst": {
            "terms": {
              "field": "sentinel_hostname_lan",
              "size": 2000
            }
          }
        }
      }
    }
  }
}

共有1个答案

申屠洛华
2023-03-14

我认为您遇到的问题是范围部分。尝试将其移动到布尔中:

{
  "query": {
    "bool": {
      "should": [{
          "bool": {
            "must": [{
                "term": {
                  "attack_ip": "10.89.7.117"
                }
              },
              {
                "term": {
                  "sentinel_port": "17"
                }
              }
            ]
          }
        },
        {
          "term": {
            "attack_ip": "10.89.7.118"
          }
        }
      ],
      "must": {
        "range": {
          "eventtime": {
            "gte": "2018-03-05T12:47:22.397+01:00"
          }
        }
      }
    }
  },
  "size": 0,
  "aggs": {
    "src": {
      "terms": {
        "field": "attack_ip",
        "size": 1000
      },
      "aggs": {
        "dst": {
          "terms": {
            "field": "sentinel_hostname_lan",
            "size": 2000
          }
        }
      }
    }
  }
}

或将其移动到筛选节:

{
  "query": {
    "bool": {
      "should": [{
          "bool": {
            "must": [{
                "term": {
                  "attack_ip": "10.89.7.117"
                }
              },
              {
                "term": {
                  "sentinel_port": "17"
                }
              }
            ]
          }
        },
        {
          "term": {
            "attack_ip": "10.89.7.118"
          }
        }
      ],
      "filter": {
        "bool": {
          "must": [{
            "range": {
              "eventtime": {
                "gte": "2018-03-05T12:47:22.397+01:00"
              }
            }
          }]
        }
      }
    }
  },
  "size": 0,
  "aggs": {
    "src": {
      "terms": {
        "field": "attack_ip",
        "size": 1000
      },
      "aggs": {
        "dst": {
          "terms": {
            "field": "sentinel_hostname_lan",
            "size": 2000
          }
        }
      }
    }
  }
}

我希望我的格式是正确的。如果你有任何问题,请让我知道。

最后,您可能需要为bool查询指定minimum_should_matchparam,以获得正确的结果。

 类似资料:
  • 我有以下三张桌子 教室 注册学生 iduser_idclass_id 帖子 模型 Classroom.php 注册学生。php 邮递php 现在我需要获得某个班级的所有帖子,学生在该班级注册。 例如,一名学生注册了教室表中id号为1的班级。所以在registered_students表中会注意到,这个特定的用户是在这个特定的类下注册的。每个类在post表中可能有多个post。用户需要获得他类的所有

  • 我有这样嵌套条目的文档: 因此,第二个条目中的*是实际的字符串值,而不是通配符。 现在,我正尝试使用以下主体查询具有key1:value3和key2:*的所有文档: 但是,这根本不会返回任何文档。 此外,使用“\\*”作为key2的查询参数也没有帮助。 是否有可能将*作为实际的String值而不是通配符查询? 第一次回答后编辑,并提示Analyzer设置:尝试将我的索引配置为使用映射字符过滤器,如

  • 我想知道JPQL是否可以嵌套查询。我正在学习Spring Data JPA,我也上传了几个相关的问题。 如果MySQL中有以下sql,我如何生成JPQL: 我有两个实体。 上面的实体有一个@OneTo多集合,集合实体在下面。 我想得到不到10个孩子的作弊实体。

  • 和相应的查询解析器 这里的主要想法只是有一个过滤器,可以看到什么食谱有一些成分,用户会通过应用程序通知。 我使用数据库中的所有食谱获得了“recipe”查询,但我需要一个获取这些食谱的查询,然后使用field comprient进行筛选,例如: 食谱-糖蛋糕,配料:糖、蜂蜜、四个… 配方-天鹅绒蛋糕,配料:糖、香草、... 并且用户通知Sugar,API应该返回这2个食谱,但是如果用户通知Suga

  • 我正试图用jooq编写这个查询 我尝试了几件事,但没有成功。到目前为止,我只得到 如何将num列添加到结果中?感谢您的帮助。

  • 我试图创建一个嵌套查询,它将过滤掉一些带有特定术语的文档。在本例中,我试图过滤掉在user.first中有匹配术语的文档。数据示例: 我的查询没有得到所需的结果,因为它返回给我所有未筛选的记录。我尝试使用: 我希望这里得到与过滤器不匹配的文档。在这种情况下,它应该只返回第二个文档。做这件事的正确方法是什么?