跳到主要内容
版本:v2.5.x

可归零和默认值

Milvus 允许你为标量字段(主字段除外)设置nullable 属性和默认值。对于标记为nullable=True 的字段,您可以在插入数据时跳过该字段,或直接将其设置为空值,系统会将其视为空值而不会导致错误。当字段具有默认值时,如果在插入过程中没有为该字段指定数据,系统将自动应用该值。

默认值和可归零属性允许处理带有空值的数据集并保留默认值设置,从而简化了从其他数据库系统到 Milvus 的数据迁移。在创建 Collection 时,也可以启用可归零属性或为可能存在不确定值的字段设置默认值。

限制

  • 只有标量字段(主字段除外)支持默认值和 nullable 属性。

  • JSON 和数组字段不支持默认值。

  • 默认值或 nullable 属性只能在创建 Collection 时配置,之后不能修改。

  • 启用了可归零属性的标量字段不能在分组搜索中用作group_by_field 。有关分组搜索的更多信息,请参阅分组搜索

  • 标记为可归零的字段不能用作 Partition Key。有关 Partition Key 的更多信息,请参阅使用 Partition Key

  • 在启用了可归零属性的标量字段上创建索引时,索引将排除空值。

  • JSON 和 ARRAY 字段:当使用IS NULLIS NOT NULL 操作符对 JSON 或 ARRAY 字段进行筛选时,这些操作符在列级别工作,这表明它们只评估整个 JSON 对象或数组是否为空。例如,如果 JSON 对象中的某个键为空,IS NULL 过滤器将无法识别该键。有关详细信息,请参阅基本操作符

Nullable 属性

通过nullable 属性,可以在 Collection 中存储空值,从而在处理未知数据时提供灵活性。

设置 nullable 属性

创建 Collection 时,使用nullable=True 定义可归零字段(默认为False )。下面的示例创建了一个名为my_collection 的 Collection,并将age 字段设置为可归零:

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri='http://localhost:19530')

# Define collection schema
schema = client.create_schema(
auto_id=False,
enable_dynamic_schema=True,
)

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
schema.add_field(field_name="age", datatype=DataType.INT64, nullable=True) # Nullable field

# Set index params
index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="AUTOINDEX", metric_type="L2")

# Create collection
client.create_collection(collection_name="my_collection", schema=schema, index_params=index_params)

插入实体

在可空字段中插入数据时,插入空值或直接省略该字段:

data = [
{"id": 1, "vector": [0.1, 0.2, 0.3, 0.4, 0.5], "age": 30},
{"id": 2, "vector": [0.2, 0.3, 0.4, 0.5, 0.6], "age": None},
{"id": 3, "vector": [0.3, 0.4, 0.5, 0.6, 0.7]}
]

client.insert(collection_name="my_collection", data=data)

使用空值进行搜索和查询

使用search 方法时,如果字段包含null 值,则搜索结果将以空值返回该字段:

res = client.search(
collection_name="my_collection",
data=[[0.1, 0.2, 0.4, 0.3, 0.128]],
limit=2,
search_params={"params": {"nprobe": 16}},
output_fields=["id", "age"]
)

print(res)

# Output
# data: ["[{'id': 1, 'distance': 0.15838398039340973, 'entity': {'age': 30, 'id': 1}}, {'id': 2, 'distance': 0.28278401494026184, 'entity': {'age': None, 'id': 2}}]"]

当您使用query 方法进行标量过滤时,空值的过滤结果都是 false,表示不会选择它们。

# Reviewing previously inserted data:
# {"id": 1, "vector": [0.1, 0.2, ..., 0.128], "age": 30}
# {"id": 2, "vector": [0.2, 0.3, ..., 0.129], "age": None}
# {"id": 3, "vector": [0.3, 0.4, ..., 0.130], "age": None} # Omitted age column is treated as None

results = client.query(
collection_name="my_collection",
filter="age >= 0",
output_fields=["id", "age"]
)

# Example output:
# [
# {"id": 1, "age": 30}
# ]
# Note: Entities with `age` as `null` (id 2 and 3) will not appear in the result.

要返回具有null 值的实体,可在不使用任何标量过滤条件的情况下进行如下查询:

说明

query 方法在不带任何过滤条件的情况下使用时,会检索 Collection 中的所有实体,包括具有空值的实体。要限制返回实体的数量,必须指定limit 参数。

null_results = client.query(
collection_name="my_collection",
filter="", # Query without any filtering condition
output_fields=["id", "age"],
limit=10
)

# Example output:
# [{"id": 2, "age": None}, {"id": 3, "age": None}]

默认值

默认值是分配给标量字段的预设值。如果在插入时没有为有默认值的字段提供值,系统会自动使用默认值。

设置默认值

创建 Collection 时,使用default_value 参数定义字段的默认值。下面的示例显示了如何将age 的默认值设置为18 ,将status 的默认值设置为"active"

schema = client.create_schema(
auto_id=False,
enable_dynamic_schema=True,
)

schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
schema.add_field(field_name="age", datatype=DataType.INT64, default_value=18)
schema.add_field(field_name="status", datatype=DataType.VARCHAR, default_value="active", max_length=10)

index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="AUTOINDEX", metric_type="L2")

client.create_collection(collection_name="my_collection", schema=schema, index_params=index_params)

插入实体

插入数据时,如果省略有默认值的字段或将其值设为空,系统就会使用默认值:

data = [
{"id": 1, "vector": [0.1, 0.2, ..., 0.128], "age": 30, "status": "premium"},
{"id": 2, "vector": [0.2, 0.3, ..., 0.129]}, # `age` and `status` use default values
{"id": 3, "vector": [0.3, 0.4, ..., 0.130], "age": 25, "status": None}, # `status` uses default value
{"id": 4, "vector": [0.4, 0.5, ..., 0.131], "age": None, "status": "inactive"} # `age` uses default value
]

client.insert(collection_name="my_collection", data=data)
说明

有关可空值和默认值设置如何生效的更多信息,请参阅适用规则

使用默认值进行搜索和查询

在向量搜索和标量过滤过程中,包含默认值的实体与其他实体的处理方式相同。您可以将默认值作为searchquery 操作符的一部分。

例如,在search 操作符中,将age 设置为默认值18 的实体将包含在结果中:

res = client.search(
collection_name="my_collection",
data=[[0.1, 0.2, 0.4, 0.3, 0.5]],
search_params={"params": {"nprobe": 16}},
filter="age == 18", # 18 is the default value of the `age` field
limit=10,
output_fields=["id", "age", "status"]
)

print(res)

# Output
# data: ["[{'id': 2, 'distance': 0.050000004, 'entity': {'id': 2, 'age': 18, 'status': 'active'}}, {'id': 4, 'distance': 0.45000002, 'entity': {'id': 4, 'age': 18, 'status': 'inactive'}}]"]

query 操作符中,可以直接通过默认值进行匹配或过滤:

# Query all entities where `age` equals the default value (18)
default_age_results = client.query(
collection_name="my_collection",
filter="age == 18",
output_fields=["id", "age", "status"]
)

# Query all entities where `status` equals the default value ("active")
default_status_results = client.query(
collection_name="my_collection",
filter='status == "active"',
output_fields=["id", "age", "status"]
)

适用规则

下表总结了可空列和默认值在不同配置组合下的行为。这些规则决定了 Milvus 在尝试插入空值或未提供字段值时如何处理数据。

| 可归零

|

默认值

|

默认值类型

|

用户输入

|

结果

|

示例

| | --- | --- | --- | --- | --- | --- | |

|

|

非空

|

无/空

|

使用默认值

|

字段: age 默认值:18

用户输入:空

结果:存储为18

| |

|

|

-

|

无/空

|

存储为空

|

字段: middle_name 默认值: -

用户输入:空

结果:存储为空

| |

|

|

非空

|

无/空

|

使用默认值

|

字段: status 默认值:"active"

用户输入:空

结果:存储为"active"

| |

|

|

-

|

无/空

|

抛出错误

|

字段: email 默认值:-

用户输入:空

结果:操作被拒绝,系统提示错误

| |

|

|

|

无/空

|

抛出错误

|

字段: username 默认值:空

用户输入:空

结果:操作符被拒绝,系统提示错误

|