MUST_NOT not working with EXIST in NESTED query

ES 5.2.2
Here is my mapping:

PUT players
{
   "mappings": {
      "players": {
         "properties": {
            "features": {
               "type": "nested",
               "properties": {
                  "name": {
                     "type": "text",
                     "fields": {
                        "keyword": {
                           "type": "keyword",
                           "ignore_above": 256
                        }
                     }
                  },
                  "value": {
                     "type": "long"
                  }
               }
            },
            "name": {
               "type": "text",
               "fields": {
                  "keyword": {
                     "type": "keyword",
                     "ignore_above": 256
                  }
               }
            }
         }
      }
   }
}

And some docs:

PUT players/players/1
{
    "name": "test"
}

PUT players/players/2
{
    "name": "Neuer",
    "features": [{
        "name": "handling",
        "value": 94
    }]
}

PUT players/players/3
{
    "name": "Lewandowski",
    "features": [{
        "name": "positioning",
        "value": 85
    }]
}

Now, I want to get players that do not have features at all.

I started with simple query to get players with no features - but it returns all players.

POST players/players/_search
{
   "query": {
      "bool": {
         "filter": [
            {
               "bool": {
                  "must_not": [
                     {
                        "exists": {
                           "field": "features"
                        }
                     }
                  ]
               }
            }
         ]
      }
   }
}

So I tried a nested query, but it returns no result.

POST players/players/_search
{
   "query": {
      "bool": {
         "filter": [
            {
               "nested": {
                  "path": "features",
                  "query": {
                     "bool": {
                        "must_not": [
                           {
                              "exists": {
                                 "field": "features"
                              }
                           }
                        ]
                     }
                  }
               }
            }
         ]
      }
   }
}

but the reversed query returns 2 elements so it is OK.

POST players/players/_search
{
   "query": {
      "bool": {
         "filter": [
            {
               "nested": {
                  "path": "features",
                  "query": {
                     "bool": {
                        "must": [
                           {
                              "exists": {
                                 "field": "features"
                              }
                           }
                        ]
                     }
                  }
               }
            }
         ]
      }
   }
}

How the query should look like to get players with no features?

If instead of putting the must_not inside your nested query, you put the nested query inside of a must_not, it should work:

POST players/players/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "nested": {
            "path": "features",
            "query": {
              "exists": {
                "field": "features"
              }
            }
          }
        }
      ]
    }
  }
}
7 Likes

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