Querying Nested Fields with OR and IN clause

This is a snippet of my ES document:

        "actions": [
            {
              "action_type": "special_offer",
              "startdate": "2019-09-10 00:00:00",
              "enddate": "2019-12-19 23:59:59"
            },
           {
              "action_type": "clean_up",
              "startdate": null,
              "enddate": null
            }
          ]

I would like to have all products with an action_type IN ('special_offer', 'clean_up', 'sell_off') and where the enddate is greater than now() OR the enddate is null.

This is how my query looks like now:

"query": {
    "bool": {
      "must": [

        {
          "nested" : {
              "path": "article.actions",
              "query" :{
                  "bool" : {
                      "should" : [
                        { "match" : {"article.actions.action_type" : "sell_off"} },
                        { "match" : {"article.actions.action_type" : "special_offer"} },
                        { "match" : {"article.actions.action_type" : "clean_up"} }
                      ],
                      "must": [
                        {
                          "range": {
                            "article.actions.enddate": {
                              "gte": "2019-10-24 00:00:00"
                            }
                          }
                        }
                      ],
                      "minimum_should_match" : 1
                  }
              }
          }
        }
      ]
    }
}

I do not know how to add the OR condition (enddate is null).

Would be happy if someone can help me.

Is the data type of field action_type is keyword or does it have a subfield of type keyword?

Update your query as below:

{
  "query": {
    "nested": {
      "path": "article.actions",
      "query": {
        "bool": {
          "must": [
            {
              "terms": {
                "article.actions.action_type.keyword": [
                  "sell_off",
                  "special_offer",
                  "clean_up"
                ]
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "range": {
                      "article.actions.enddate": {
                        "gte": "now/d"
                      }
                    }
                  },
                  {
                    "bool": {
                      "must_not": [
                        {
                          "exists": {
                            "field": "article.actions.enddate"
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

For null check you have to use exists query and place it along with the range query inside a should block.

Also I have assumed that field action_type has a subfield of type keyword. This will help you build the IN type of query using terms query.

1 Like

Thank you so much for your solution. It works.

The datatype of action_type is keyword.

That's the mapping:

 "actions": {
          "type": "nested",
          "properties": {
            "action_type": {
              "type": "keyword"
            },
            "startdate": {
              "format": "yyyy-MM-dd HH:mm:ss",
              "type": "date"
            },
            "enddate": {
              "format": "yyyy-MM-dd HH:mm:ss",
              "type": "date"
            }
          }
        }

I had to remove the word keyword from the query. Otherwise it does not work.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.