跳到主要内容

开启动态字段

本小节将介绍如何使用 Collection 中预留的动态字段灵活存取数据。

概述

在 Zilliz Cloud 上,您可以通过设置 Collection 各字段的名称及数据类型来创建 Collection 的 Schema。在完成字段创建后,您还可以为各字段创建索引来提升检索效率。

当您在 Schema 中增加一个字段后,您应该确保待插入数据里包含该字段。如果您的数据集各条记录包含的字段不一致,您可能就会用到预留的动态字段。

动态字段是一个名为 $meta 的预留 JavaScript Object Notation (JSON) 字段。待插入数据中的所有未在 Schema 中定义的字段都会以键值对的方式存放在这个预留的 JSON 字段里。对于开启了动态字段的 Collection 而言,您可以轻松完成针对任何字段的标量查询,无论该字段是 Schema 中定义了的静态字段还是 $meta 中存放的动态字段。

开启动态字段

如需开启动态字段,需要在定义 Schema 时将 enable_dynamic_field 设置为 True。开启动态字段后,待插入数据中的所有未定义字段将以键值对的形式存入预留的动态字段中。

如下代码使用快速建表方式创建了一个包含两个静态字段的 Collection,并开启了动态字段。

import random, time
from pymilvus import connections, MilvusClient, DataType

CLUSTER_ENDPOINT = "YOUR_CLUSTER_ENDPOINT"
TOKEN = "YOUR_CLUSTER_TOKEN"

# 1. Set up a Milvus client
client = MilvusClient(
uri=CLUSTER_ENDPOINT,
token=TOKEN
)

# 2. Create a collection
schema = MilvusClient.create_schema(
auto_id=False,
# highlight-next-line
enable_dynamic_field=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)

index_params = MilvusClient.prepare_index_params()

index_params.add_index(
field_name="id",
index_type="STL_SORT"
)

index_params.add_index(
field_name="vector",
index_type="IVF_FLAT",
metric_type="L2",
params={"nlist": 1024}
)

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

res = client.get_load_state(
collection_name="test_collection"
)

print(res)

# Output
#
# {
# "state": "<LoadState: Loaded>"
# }

动态插入数据

Collection 创建完成后,您就可以向该 Collection 中插入 Schema 中未定义的字段了。

准备数据

在如下代码中,我们准备了一些随机生成的数据。

colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []

for i in range(1000):
current_color = random.choice(colors)
current_tag = random.randint(1000, 9999)
data.append({
"id": i,
"vector": [ random.uniform(-1, 1) for _ in range(5) ],
"color": current_color,
"tag": current_tag,
"color_tag": f"{current_color}_{str(current_tag)}"
})

print(data[0])

您可以打印第一行数据查看随机生成的数据结构。

{
id: 0,
vector: [
0.1275656405044483,
0.47417858592773277,
0.13858264437643286,
0.2390904907020377,
0.8447862593689635
],
color: 'blue',
tag: 2064,
color_tag: 'blue_2064'
}

插入数据

数据准备完成后便可以开始插入数据了。

res = client.insert(
collection_name="test_collection",
data=data,
)

print(res)

# Output
#
# {
# "insert_count": 1000,
# "ids": [
# 0,
# 1,
# 2,
# 3,
# 4,
# 5,
# 6,
# 7,
# 8,
# 9,
# "(990 more items hidden)"
# ]
# }

time.sleep(5)

使用动态字段进行搜索

如果前面的所有步骤都已完成,我们就可以在搜索或查询的表达式中使用动态字段。

# 4. Search with dynamic fields
query_vectors = [[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]]

res = client.search(
collection_name="test_collection",
data=query_vectors,
filter="color in [\"red\", \"green\"]",
search_params={"metric_type": "L2", "params": {"nprobe": 10}},
limit=3
)

print(res)

# Output
#
# [
# [
# {
# "id": 863,
# "distance": 0.188413605093956,
# "entity": {
# "id": 863,
# "color_tag": "red_2371"
# }
# },
# {
# "id": 799,
# "distance": 0.29188022017478943,
# "entity": {
# "id": 799,
# "color_tag": "red_2235"
# }
# },
# {
# "id": 564,
# "distance": 0.3492690920829773,
# "entity": {
# "id": 564,
# "color_tag": "red_9186"
# }
# }
# ]
# ]

小结

值得注意的是,colortagcolor_tag 没有预先定义在 Schema 中,但这也并不影响在表达式和输出字段中使用它们。

如果动态字段包含了除数字、字母及下划线之外的诸如加号(+)、星号(*)或美元符号($)等其它特殊字符,我们需要使用$meta[]关键字在表达式或输出字段中引入这些字段。

... 
expr='$meta["$key"] in ["a", "b", "c"]',
output_fields='$meta["$key"]'
...