如何嵌套bool查询?

时间:2018-03-05 12:59:46

标签: elasticsearch

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

OR (

AND (
    condition
    condition
    ...
)

AND (
    condition
    condition
    ...
)

)

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

由我的代码生成的此类结构的示例(这是完整的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"
  • if "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约束移动到布尔部分。但是我得到了同样的错误。

我的查询为available online for easier reading,转载如下:

{
  "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 个答案:

答案 0 :(得分:2)

我认为你遇到的问题是range部分。尝试将其移到bool

{
  "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
          }
        }
      }
    }
  }
}

或将其移至filter部分:

{
  "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
          }
        }
      }
    }
  }
}

我希望我正确地格式化了这个。如果您有任何问题,请告诉我。

最后,您可能需要为minimum_should_match指定bool query参数才能获得正确的结果。