WoJ
WoJ

Reputation: 29957

How to nest bool queries?

I am building a search query which dynamically adds a set of constraints (bool) to the query. The general expected structure is as follows

OR (

AND (
    condition
    condition
    ...
)

AND (
    condition
    condition
    ...
)

)

In other words I have a set (one or more) of conditions which must all be met (AND above). There may be several of such sets, any of them should be enough for the final match (the OR above).

An example of such structure, as generated by my code (this is the full API query, the generated part is "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
          }
        }
      }
    }
  }
}

My understanding of this query was:

the entry will match

Unfortunately I get upon calling Elasticsearch the error

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

What does this error mean?

EDIT

Following Piotr's answer, I tried to move the range constraint into the boolean part. I get the same error, though.

My query is available online for easier reading and reproduced below:

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

Upvotes: 0

Views: 664

Answers (1)

Piotr Pradzynski
Piotr Pradzynski

Reputation: 4535

I think the problem you have is with range part. Try to move it inside the 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
          }
        }
      }
    }
  }
}

or move it to filter section:

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

I hope I formatted this correctly. Please let me know if you have any issues.

In the end, it is possible that you will need to specify minimum_should_match param for bool query to get correct results.

Upvotes: 2

Related Questions