3

Let's say we have nested object comment with two properties tag and group. If I do below query then it gives me the desired result.

{
  "query": {
    "bool": {
      "must": {
        "nested": {
          "query": {
            "bool": {
              "must": {
                "match": {
                  "comment.tag": {
                    "query": "SPRING",
                    "type": "boolean"
                  }
                }
              },
              "must_not": {
                "match": {
                  "comment.group": {
                    "query": "ABC",
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "path": "comment"
        }
      }
    }
  }
}

But if I execute below query then it doesn't give me the desired result.

{
  "query": {
    "bool": {
      "must": {
        "nested": {
          "query": {
            "bool": {
              "must": {
                "match": {
                  "comment.tag": {
                    "query": [
                      "SPRING",
                      "HIBERNATE"
                    ],
                    "type": "boolean"
                  }
                }
              },
              "must_not": {
                "match": {
                  "comment.group": {
                    "query": [
                      "ABC",
                      "XYZ"
                    ],
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "path": "comment"
        }
      }
    }
  }
}

The difference between these two is that I am querying both properties of nested object against multiple values.

With second query it just picks up the last values in the list provided to search and returns the result.

Is there a way to write query where I can specify pass list of values and all values are included in search?

1 Answer 1

3

This has nothing to do with being a nested query/filter. Instead, it's how you are using the match query. It does not expect an array of values.

There are really two ways to achieve what you appear to be trying. Before going into them, I did want to note that the match query defaults to using the boolean type, so you can leave that out.

  1. You can change the match query to simply supply both values in the string. Order is irrelevant:

    "bool" : {
      "must" : {
        "match" : {
          "comment.tag" : "SPRING HIBERNATE"
        }
      }
    }
    

    The reason that this works is because the field will use the search analyzer to tokenize the string in the same way that the field is indexed (by default). As a result, assuming a default string analyzer, you will end up searching for spring or hibernate. Because you are not using phrase matching, order is truly irrelevant.

  2. The other way is to explicitly separate them using the outer bool/must query (the same applies to the must_not and should). Since you want them treated like ORs, you need to use should instead of must this way:

    "bool" : {
      "should" : [
        {
          "match" : { "company.tag" : "SPRING" }
        },
        {
          "match" : { "company.tag" : "HIBERNATE" }
        }
      ]
    }
    

    Note: If you also include a must, then you need to set minimum_should_match to 1 (inside of the bool object) so that it does not become optional. Without the must and must_not, it is implicitly 1.

Sign up to request clarification or add additional context in comments.

2 Comments

First solution does work but the second one did not work. Thanks for your help on this.
Oh, woops. The second one should be should in place of must so that it is treated like an or instead of and.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.