将数据插入 StructArray 字段
当每个实体包含一个有序的结构化元素列表时,可将数据插入到 StructArray 字段中。在插入有效载荷中,StructArray 字段表示为一个对象数组。每个对象代表一个 Struct 元素,并使用 Collection 模式中定义的 Struct 子字段名称。
本页使用《创建 StructArray 字段》中的tech_articles Collection。每个实体都是一篇技术文章,而chunks 字段将文章片段作为 Struct 元素进行存储。
开始之前
请确保Collection Schema中已包含chunks StructArray字段。
| 字段 | 类型 | 插入值 |
|---|---|---|
doc_id | INT64 | 文章 ID。 |
title | VARCHAR | 文章标题。 |
category | VARCHAR | 文章分类。 |
title_vector | FLOAT_VECTOR | 文章级Embeddings。 |
chunks | ARRAY | 一段对象列表。 |
chunks 中的每个对象都必须遵循 Struct Schema。
| 子字段 | 类型 | 插入值 |
|---|---|---|
text | VARCHAR | 块文本。 |
section | VARCHAR | 部分名称,例如index 、search 或filter 。 |
page | INT64 | 页码或逻辑位置。 |
quality_score | FLOAT | 片段级评分。 |
has_code | BOOL | 该片段是否包含代码。 |
emb_list_vector | FLOAT_VECTOR | 为 EmbeddingList 搜索编写的向量。 |
emb | FLOAT_VECTOR | 为元素级搜索编写的向量。 |
在插入有效载荷中,chunks 是一个常规字段,其值为一个Struct对象数组。在每个对象内部,请使用text 和emb 等子字段名称。仅在插入完成后创建索引、运行搜索、构建过滤器或指定输出字段时,才使用chunks[text] 或chunks[emb] 等路径语法。
了解插入有效载荷的结构
chunks 的值是一个由 Struct 元素组成的数组。每个元素都是一个对象,其键为子字段名称。
{
"doc_id": 1,
"title": "StructArray indexing patterns",
"category": "index",
"title_vector": [0.12, 0.08, 0.32, 0.48],
"chunks": [
{
"text": "Create one index for each vector subfield.",
"section": "index",
"page": 1,
"quality_score": 0.96,
"has_code": false,
"emb_list_vector": [0.10, 0.20, 0.30, 0.40],
"emb": [0.10, 0.20, 0.30, 0.40]
},
{
"text": "Use MAX_SIM metrics for EmbeddingList search.",
"section": "index",
"page": 2,
"quality_score": 0.91,
"has_code": true,
"emb_list_vector": [0.16, 0.24, 0.35, 0.45],
"emb": [0.16, 0.24, 0.35, 0.45]
}
]
}
emb_list_vector 和emb 是独立的向量子字段,因为它们支持不同的搜索模式。EmbeddingList 搜索将 StructArray 字段中的所有向量视为一个嵌入列表,并返回带有MAX_SIM* 指标的实体级结果。元素级搜索则独立搜索每个 Struct 元素,并可返回匹配元素的偏移量。为简化起见,本示例在两个字段中存储了相同的向量值。 在生产应用中,当两种搜索模式使用相同的块Embeddings时,可以在这两个子字段中存储相同的Embeddings;当两种搜索模式使用不同的表示形式时,则可以存储不同的Embeddings。
插入行
使用 `client.insert() ` 插入包含 StructArray 值的行。
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus",
)
data = [
{
"doc_id": 1,
"title": "StructArray indexing patterns",
"category": "index",
"title_vector": [0.12, 0.08, 0.32, 0.48],
"chunks": [
{
"text": "Create one index for each vector subfield.",
"section": "index",
"page": 1,
"quality_score": 0.96,
"has_code": False,
"emb_list_vector": [0.10, 0.20, 0.30, 0.40],
"emb": [0.10, 0.20, 0.30, 0.40],
},
{
"text": "Use MAX_SIM metrics for EmbeddingList search.",
"section": "index",
"page": 2,
"quality_score": 0.91,
"has_code": True,
"emb_list_vector": [0.16, 0.24, 0.35, 0.45],
"emb": [0.16, 0.24, 0.35, 0.45],
},
],
},
{
"doc_id": 2,
"title": "Filtered StructArray search",
"category": "filter",
"title_vector": [0.20, 0.18, 0.22, 0.40],
"chunks": [
{
"text": "Use element_filter to match scalar conditions within the same Struct element.",
"section": "filter",
"page": 1,
"quality_score": 0.93,
"has_code": True,
"emb_list_vector": [0.21, 0.18, 0.33, 0.44],
"emb": [0.21, 0.18, 0.33, 0.44],
},
{
"text": "MATCH_LEAST checks how many elements satisfy a predicate.",
"section": "filter",
"page": 2,
"quality_score": 0.88,
"has_code": False,
"emb_list_vector": [0.24, 0.22, 0.31, 0.39],
"emb": [0.24, 0.22, 0.31, 0.39],
},
],
},
{
"doc_id": 3,
"title": "Element-level search with offsets",
"category": "search",
"title_vector": [0.33, 0.11, 0.29, 0.37],
"chunks": [
{
"text": "Element-level search can return the offset of the matched Struct element.",
"section": "search",
"page": 1,
"quality_score": 0.95,
"has_code": False,
"emb_list_vector": [0.32, 0.14, 0.28, 0.41],
"emb": [0.32, 0.14, 0.28, 0.41],
}
],
},
]
result = client.insert(
collection_name="tech_articles",
data=data,
)
print(result)
插入可为空的 StructArray 字段
如果chunks 字段是可空的,则实体可以将整个chunks 字段设置为null。在Python中,使用None 来表示null值。
client.insert(
collection_name="tech_articles",
data=[
{
"doc_id": 10,
"title": "Article without chunks yet",
"category": "draft",
"title_vector": [0.05, 0.10, 0.15, 0.20],
"chunks": None,
}
],
)
当可为空的 StructArray 字段包含一个有效的 StructArray 值时,该值中的所有子字段应均为空或具有有效值。若插入的实体中部分子字段设为空而其他子字段设为有效值,则会引发错误。
警告
可为空的 StructArray 字段仅在 Milvus v3.0.x 中可用。若向现有 Collection 动态添加 StructArray 字段,则该新增字段必须为可为空类型,且现有实体针对该新字段的所有子字段均应返回 `null `。
验证插入的数据
您可以查询 Collection 并返回 StructArray 字段或选定的子字段。
rows = client.query(
collection_name="tech_articles",
filter="doc_id in [1, 2, 3]",
output_fields=[
"doc_id",
"title",
"chunks[text]",
"chunks[section]",
"chunks[quality_score]",
],
)
for row in rows:
print(row)
仅在查询、搜索、过滤或创建索引时使用 StructArray 字段路径(例如chunks[text] )。插入有效负载时仍应使用chunks 下的嵌套对象。
插入规则
| 规则 | 说明 |
|---|---|
| 对于 StructArray 字段,请使用对象数组。 | chunks 的值是一个列表,列表中的每个项目都是一个 Struct 元素。 |
| 在每个 Struct 元素内部使用子字段名称。 | 将{"text": "...", "emb": [...]} 插入chunks 中,而非{"chunks[text]": "..."} 中。 |
| 需符合 Struct Schema。 | 每个 Struct 元素必须使用 Struct Schema 中定义的子字段。 |
| 向量维度必须匹配。 | 向量值必须与为其向量子字段配置的dim 相匹配。 |
遵守max_capacity 。 | 一个实体中的 Struct 元素数量不得超过 StructArray 字段的max_capacity 。 |
| 针对不同的搜索模式,请使用单独的向量子场。 | 如果同时需要 EmbeddingList 搜索和元素级搜索,请将向量值写入两个向量子字段。 |
仅当字段允许为空时,才使用null 。 | 非可空的 StructArray 字段需要有效的 StructArray 值。 |
常见错误
在插入有效载荷中使用诸如
chunks[text]之类的字段路径。从 Struct 元素中省略必需的子字段。
插入维度错误的向量。
插入的 Struct 元素数量超过了
max_capacity允许的数量。仅将一个子字段设置为
null,而同一StructArray值中的其他子字段却有效。仅将向量写入
emb_list_vector,随后尝试在chunks[emb]上执行元素级搜索。仅将向量写入
emb,随后尝试在chunks[emb_list_vector]上执行EmbeddingList搜索。
后续步骤
要为
chunks[emb_list_vector]、chunks[emb]以及标量子字段创建索引,请参阅《索引 StructArray 字段》。要搜索 StructArray 向量子字段,请参阅《使用 StructArray 进行基本向量搜索》。
要了解可为空行为和特定版本的限制,请参阅《StructArray 限制》。