Elasticsearch query behaviour

250 Views Asked by At

I've got two different queries against my elasticsearch. The difference between these two queries is that the first one got the two search criteria in one boolean should query and he second splits it into two single bool should queries. The first one return the expected response but the second one doesnt match to any document even if there are documents which contains both criteria. If i refactor the second one so that the two splitted bool should queries are encapsulatec by a bool should querie it returns the expected response like it is for querie 1.

The question is why does query 2 doesn't return the response as 1 and 3 do? Am i missing something?

EDIT: provided example data

EDIT: my problem solved, it was just a spelling mistake while building the range query in my code and i doesnt recognize it -.- but maybe the explanation from the answer here will help somebody else.

1.

GET _search
{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              {
                "range": {
                  "streetNr": {
                    "from": "1",
                    "to": "100",
                    "include_lower": true,
                    "include_upper": true,
                    "boost": 1
                  }
                }
              },
              {
                "match": {
                  "geographicAddress.city": {
                    "query": "Berlin"
                  }
                }
              }
            ],
            "minimum_should_match": "1"
          }
        }
      ]
    }
  }
}
GET _search
{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              {
                "range": {
                  "streetNr": {
                    "from": "1",
                    "to": "100",
                    "include_lower": true,
                    "include_upper": true,
                    "boost": 1
                  }
                }
              }
            ],
            "minimum_should_match": "1"
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "geographicAddress.city": {
                    "query": "Berlin"
                  }
                }
              }
            ],
            "minimum_should_match": "1"
          }
        }
      ]
    }
  }
}
GET _search
{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              {
                "bool": {
                  "should": [
                    {
                      "range": {
                        "streetNr": {
                          "from": "1",
                          "to": "100",
                          "include_lower": true,
                          "include_upper": true,
                          "boost": 1
                        }
                      }
                    }
                  ],
                  "minimum_should_match": "1"
                }
              },
              {
                "bool": {
                  "should": [
                    {
                      "match": {
                        "geographicAddress.city": {
                          "query": "Berlin"
                        }
                      }
                    }
                  ],
                  "minimum_should_match": "1"
                }
              }
            ],
            "minimum_should_match": "1"
          }
        }
      ]
    }
  }
}

Example data:

      {
        "_index": "stof_64371064",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.0,
        "_source": {
          "streetNr": 90,
          "geographicAddress": {
            "city": "Berlin"
          }
        }
      },
      {
        "_index": "stof_64371064",
        "_type": "_doc",
        "_id": "2",
        "_score": 0.0,
        "_source": {
          "streetNr": 10,
          "geographicAddress": {
            "city": "Berlin"
          }
        }
      }
2

There are 2 best solutions below

7
On

Please refer ES official documentation on bool query, to get a detailed understanding of various clauses.

The structure of your first search query is like -

 {
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              {},
              {}
            ],
            "minimum_should_match": 1
          }
        }
      ]
    }
  }
}

filter clause is wrapping should query, but at the end of should clause, "minimum_should_match": 1 is added which indicates that 1 should clause must be mandatory.

The structure of your second search query is like -

{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": {},
            "minimum_should_match": "1"
          }
        },
        {
          "bool": {
            "should": {},
            "minimum_should_match": "1"
          }
        }
      ]
    }
  }
}

Here since you have added "minimum_should_match": "1" after every should clause, then in a way, it acts like a must clause only, as there is only one condition that needs to be matched in the should clause. filter clause is applied enclosing both the bool should clause, so when both the should clause match, then only you will get the result.

The structure of your third search query is like -

{
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "should": [
              {
                "bool": {
                  "should": [
                    {}
                  ],
                  "minimum_should_match": 1
                }
              },
               {
                "bool": {
                  "should": [
                    {}
                  ],
                  "minimum_should_match": 1
                }
              }
            ],
            "minimum_should_match": 1
          }
        }
      ]
    }
  }
}

In this, you have used multiple combinations of the bool should clause. The first outer bool should clause, wraps two more bool should clause. But here at the end of the outer should clause you have added "minimum_should_match": 1. So though here filter clause is there but it will return a result even if one bool should clause satisfy the condition.

Adding a working example with index data, search query, and search result

Index Data:

{
  "streetNr":0,
  "geographicAddress":{
    "city":"Berlin"
  }
}
{
  "streetNr":90,
  "geographicAddress":{
    "city":"Berlin"
  }
}

Search Query: (Second search query acc to your question)

    {
  "query": {
    "bool": {
      "should": [          <-- note this
        {
          "bool": {
            "should": [
              {
                "range": {
                  "streetNr": {
                    "from": "1",
                    "to": "100",
                    "include_lower": true,
                    "include_upper": true,
                    "boost": 1
                  }
                }
              }
            ],
            "minimum_should_match": "1"
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "geographicAddress.city": {
                    "query": "Berlin"
                  }
                }
              }
            ],
            "minimum_should_match": "1"
          }
        }
      ]
    }
  }
}

Search Result:

"hits": [
      {
        "_index": "stof_64371064",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.0,
        "_source": {
          "streetNr": 90,
          "geographicAddress": {
            "city": "Berlin"
          }
        }
      },
      {
        "_index": "stof_64371064",
        "_type": "_doc",
        "_id": "2",
        "_score": 0.0,
        "_source": {
          "streetNr": 0,
          "geographicAddress": {
            "city": "Berlin"
          }
        }
      }
    ]
1
On

In the should with minimum should match=1 you say that if one of the criteria is right return the document as you have set in query 1 and 3 . But in the second query you have set two criteria inside filter and elasticsearch search and returns those documents which both criterias are valid on them. Because of that your second query behaves such as a must in comparison with should in your other queries.