#10621·qdrant

Title: is_empty filter behaves differently depending on whether the field is indexed

Author: joeinCreated Sep 12, 2026Updated Sep 12, 2026
Labelsbug

There are 2 ways to check whether a payload field is empty.

{"must":[{"is_empty":{"key":<key>}}]}

and

{"must":[{"key":<key>,"is_empty":true}]}.

On a key that resolves to a single value the two forms agree. On a key that resolves to several values they do not, and one of them also depends on whether the field is indexed.

If a payload field is not indexed and {"must":[{"key":<key>,"is_empty":true}]} is used, then this filter matches a point when any value at the key is empty, so it matches a[].b on {"a": [{"b": 1}, {"b": []}]}. In all the other cases (when the field is indexed, or when the {"must":[{"is_empty":{"key":<key>}}]} form is used) the filter matches only when every value at the key is empty, so that point does not match.

This issue looks similar to #10096 Steps to reproduce:

http
PUT collections/indexed
{
    "vectors": {
        "distance": "Dot",
        "size": 2
    }
}

PUT collections/unindexed
{
    "vectors": {
        "distance": "Dot",
        "size": 2
    }
}

PUT collections/indexed/index
{
  "field_name": "a[].b",
  "field_schema": "integer"
}

PUT collections/indexed/points
{
  "points": [
    {
      "id": 1,
      "payload": {
        "a": [
          {
            "b": 1
          },
          {
            "b": []
          }
        ]
      },
      "vector": [
        0.2,
        0.3
      ]
    },
    {
      "id": 2,
      "payload": {
        "a": [
          {
            "b": 1
          },
          {
            "b": null
          }
        ]
      },
      "vector": [
        0.2,
        0.4
      ]
    },
    {
      "id": 3,
      "payload": {
        "a": [
          {
            "b": 1
          },
          {
            "b": 2
          }
        ]
      },
      "vector": [
        0.1,
        0.4
      ]
    },
    {
      "id": 4,
      "payload": {
        "a": [
          {
            "b": []
          },
          {
            "b": []
          }
        ]
      },
      "vector": [
        0.1,
        0.5
      ]
    }
  ]
}

PUT collections/unindexed/points
{
  "points": [
    {
      "id": 1,
      "payload": {
        "a": [
          {
            "b": 1
          },
          {
            "b": []
          }
        ]
      },
      "vector": [
        0.2,
        0.3
      ]
    },
    {
      "id": 2,
      "payload": {
        "a": [
          {
            "b": 1
          },
          {
            "b": null
          }
        ]
      },
      "vector": [
        0.2,
        0.4
      ]
    },
    {
      "id": 3,
      "payload": {
        "a": [
          {
            "b": 1
          },
          {
            "b": 2
          }
        ]
      },
      "vector": [
        0.1,
        0.4
      ]
    },
    {
      "id": 4,
      "payload": {
        "a": [
          {
            "b": []
          },
          {
            "b": []
          }
        ]
      },
      "vector": [
        0.1,
        0.5
      ]
    }
  ]
}

POST collections/indexed/points/scroll
{
  "filter": {"must":[{"is_empty":{"key":"a[].b"}}]}
}

POST collections/unindexed/points/scroll
{
  "filter": {"must":[{"is_empty":{"key":"a[].b"}}]}
}

POST collections/indexed/points/scroll
{
  "filter": {"must":[{"key":"a[].b","is_empty":true}]}
}

POST collections/unindexed/points/scroll
{
  "filter": {"must":[{"key":"a[].b","is_empty":true}]}
}