Create a StructArray Field
当一个 Entity 需要包含一个有序的结构化元素列表时,可以创建 StructArray field。StructArray field 是一种 Array field,其元素类型为 Struct。每个 Struct 元素都遵循相同的 Schema,并且可以包含标量子字段、向量子字段,或同时包含两者。
本页介绍如何定义 Struct schema、将其作为 StructArray field 添加、选择后续用于 Search 和 Filter 的子字段,并了解在插入或索引数据之前适用的 Schema 规则。
准备工作
本页使用名为 tech_articles 的 Collection。每个 Entity 表示一篇技术文章,chunks 字段以 Struct 元素的形式存储 chunk 级数据。
| 字段 | 类型 | 用途 |
|---|---|---|
doc_id | INT64 | 文章的主键。 |
title | VARCHAR | 文章标题。 |
category | VARCHAR | 文章级类别。 |
title_vector | FLOAT_VECTOR | 文章级向量字段,稍后会在 Hybrid Search 示例中使用。 |
chunks | ARRAY | StructArray 字段,用于存储 chunk 级文本、元数据和 Embedding。 |
chunks StructArray 字段包含以下子字段。
| 子字段 | 类型 | 用途 |
|---|---|---|
text | VARCHAR | Chunk 文本。 |
section | VARCHAR | Section 名称,例如 index、search 或 filter。 |
page | INT64 | Chunk 的页码或逻辑位置。 |
quality_score | FLOAT | Chunk 级分数,用于标量过滤和范围示例。 |
has_code | BOOL | Chunk 是否包含代码。 |
emb_list_vector | FLOAT_VECTOR | 用于基于 MAX_SIM* metric 进行 EmbeddingList search 的向量子字段。 |
emb | FLOAT_VECTOR | 用于基于常规向量 metric 进行元素级搜索的向量子字段。 |
一个向量字段或向量子字段只能接受一个 Index。如果你同时需要 EmbeddingList search 和元素级搜索,请定义两个独立的向量子字段。在本示例中,chunks[emb_list_vector] 用于 EmbeddingList search,chunks[emb] 用于元素级搜索。
Supported subfield data types
StructArray 字段会为每个 Struct 子字段存储一个数组值。定义 Struct schema 时,请从支持的标量和向量类型系列中选择子字段类型。
| Struct 子字段物理类型 | 支持情况 | 说明 |
|---|---|---|
Array | 支持 | 将子字段定义为 DataType.BOOL。 |
Array | 支持 | 将子字段定义为 DataType.INT8、DataType.INT16、DataType.INT32 或 DataType.INT64。 |
Array | 支持 | 将子字段定义为 DataType.FLOAT 或 DataType.DOUBLE。 |
Array | 支持 | 将子字段定义为 DataType.VARCHAR 并设置 max_length。 |
ArrayOfVector | 支持 | 将子字段定义为 DataType.FLOAT_VECTOR 并设置 dim。 |
ArrayOfVector | 支持 | 将子字段定义为 DataType.FLOAT16_VECTOR 并设置 dim。 |
ArrayOfVector | 支持 | 将子字段定义为 DataType.BFLOAT16_VECTOR 并设置 dim。 |
ArrayOfVector | 支持 | 将子字段定义为 DataType.INT8_VECTOR 并设置 dim。 |
ArrayOfVector | 支持 | 将子字段定义为 DataType.BINARY_VECTOR 并设置 dim。 |
ArrayOfVector | 不支持 | StructArray 字段不支持 sparse vector 子字段。 |
Array | 不支持 | 使用 VARCHAR,而不是 String。 |
Array | 不支持 | StructArray 字段不支持 JSON 子字段。 |
Array | 不支持 | StructArray 字段不支持 Geometry 子字段和 GIS 函数。 |
Array | 不支持 | StructArray 字段不支持 Text 子字段。 |
Array | 不支持 | StructArray 字段不支持 Timestamptz 子字段和时间专用表达式。 |
嵌套的 Array、ArrayOfVector、Struct 或 ArrayOfStruct | 不支持 | StructArray 字段不能包含嵌套数组、嵌套向量数组、嵌套 Struct 字段或嵌套 Array-of-Struct 字段。 |
如需了解特定版本支持情况、nullable 行为和其他限制,请参阅 StructArray Limits。
Create a collection with a StructArray field
要创建 StructArray field,首先定义每个元素使用的 Struct schema。然后添加一个 Array field,并将其元素类型设置为 Struct。
-
创建 collection schema。
-
添加 collection-level fields,例如主键和文章级字段。
-
为存储在 StructArray field 中的元素创建 Struct schema。
-
向 Struct schema 添加 scalar 和 vector subfields。
-
添加一个 Array field,并设置
element_type=DataType.STRUCT。 -
将
struct_schema设置为该 Struct schema。 -
设置
max_capacity,限制每个 entity 可在该字段中存储的 Struct 元素数量。
from pymilvus import MilvusClient, DataType
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus",
)
schema = client.create_schema(
auto_id=False,
enable_dynamic_field=False,
)
# Collection-level fields.
schema.add_field(
field_name="doc_id",
datatype=DataType.INT64,
is_primary=True,
)
schema.add_field(
field_name="title",
datatype=DataType.VARCHAR,
max_length=512,
)
schema.add_field(
field_name="category",
datatype=DataType.VARCHAR,
max_length=128,
)
schema.add_field(
field_name="title_vector",
datatype=DataType.FLOAT_VECTOR,
dim=4,
)
# Struct schema used by each element in the StructArray field.
chunk_schema = client.create_struct_field_schema()
chunk_schema.add_field(
field_name="text",
datatype=DataType.VARCHAR,
max_length=65535,
)
chunk_schema.add_field(
field_name="section",
datatype=DataType.VARCHAR,
max_length=128,
)
chunk_schema.add_field(
field_name="page",
datatype=DataType.INT64,
)
chunk_schema.add_field(
field_name="quality_score",
datatype=DataType.FLOAT,
)
chunk_schema.add_field(
field_name="has_code",
datatype=DataType.BOOL,
)
# Vector subfield for EmbeddingList search.
chunk_schema.add_field(
field_name="emb_list_vector",
datatype=DataType.FLOAT_VECTOR,
dim=4,
)
# Vector subfield for element-level search.
chunk_schema.add_field(
field_name="emb",
datatype=DataType.FLOAT_VECTOR,
dim=4,
)
# Add the StructArray field.
schema.add_field(
field_name="chunks",
datatype=DataType.ARRAY,
element_type=DataType.STRUCT,
struct_schema=chunk_schema,
max_capacity=1000,
)
client.create_collection(
collection_name="tech_articles",
schema=schema,
)
Understand StructArray field paths
创建 StructArray 字段后,使用 structArray[subfield] 路径语法引用其子字段。创建索引、搜索向量子字段、输出子字段或构建标量 filter 时,都可以使用此语法。
| 路径 | 含义 | 常见用法 |
|---|---|---|
chunks[text] | 每个 Struct 元素中的 text 子字段。 | 输出字段或标量过滤。 |
chunks[section] | 每个 chunk 的 section 标签。 | 标量过滤。 |
chunks[quality_score] | chunk 级质量分数。 | 标量过滤或标量索引。 |
chunks[emb_list_vector] | 用作 embedding list 的向量子字段。 | 使用 MAX_SIM* 的 EmbeddingList 搜索。 |
chunks[emb] | 每个 Struct 元素独立使用的向量子字段。 | 元素级向量搜索。 |
将 StructArray 字段设置为 nullable
Milvus v3.0.x 支持 nullable StructArray 字段。nullable StructArray 字段允许 Entity 为整个 StructArray 字段存储 null。
schema.add_field(
field_name="chunks",
datatype=DataType.ARRAY,
element_type=DataType.STRUCT,
struct_schema=chunk_schema,
max_capacity=1000,
nullable=True,
)
警告
nullable StructArray 字段仅在 Milvus v3.0.x 中可用。对于 nullable StructArray 字段,Entity 可以提供有效的 StructArray 值,也可以将整个字段设置为 null。插入有效的 StructArray 值时,所有子字段都应为 NULL 或具有有效值。如果插入的 Entity 中部分子字段设置为 NULL,而其他子字段设置为有效值,则会导致错误。详情请参阅 StructArray Limits。
向现有 Collection 添加 StructArray field
Milvus v3.0.x 支持向现有 Collection 添加 StructArray field。新增的 StructArray field 必须为 nullable,因为 Collection 中已存在的 Entity 没有该新 field 的值。
要向现有 Collection 添加 StructArray field,请先定义 Struct schema。然后调用 add_collection_struct_field() 并设置 nullable=True。
chunk_schema = client.create_struct_field_schema()
chunk_schema.add_field(
field_name="text",
datatype=DataType.VARCHAR,
max_length=65535,
)
chunk_schema.add_field(
field_name="section",
datatype=DataType.VARCHAR,
max_length=128,
)
chunk_schema.add_field(
field_name="page",
datatype=DataType.INT64,
)
chunk_schema.add_field(
field_name="quality_score",
datatype=DataType.FLOAT,
)
chunk_schema.add_field(
field_name="has_code",
datatype=DataType.BOOL,
)
chunk_schema.add_field(
field_name="emb_list_vector",
datatype=DataType.FLOAT_VECTOR,
dim=4,
)
chunk_schema.add_field(
field_name="emb",
datatype=DataType.FLOAT_VECTOR,
dim=4,
)
client.add_collection_struct_field(
collection_name="tech_articles",
field_name="chunks",
struct_schema=chunk_schema,
max_capacity=1000,
nullable=True,
)
添加 StructArray field 后,对于新 field 的所有 subfield,已有 Entity 都会返回 null。
创建 StructArray field 后,不能再向该已有 StructArray field 添加新的 subfield。如果之后需要更多元素属性,请调用 drop_collection_field() 删除该 StructArray field,然后使用更新后的 Struct schema 添加新的 StructArray field。
client.drop_collection_field(
collection_name="tech_articles",
field_name="chunks",
)
client.add_collection_struct_field(
collection_name="tech_articles",
field_name="chunks",
struct_schema=updated_chunk_schema,
max_capacity=1000,
nullable=True,
)
Schema rules
| 规则 | 说明 |
|---|---|
| Struct 用作 Array 元素类型。 | 将 StructArray 字段创建为 Array 字段,并设置 element_type=STRUCT。不要将 Struct 创建为顶层 Collection 字段。 |
| 所有元素共享同一个 Schema。 | 同一 StructArray 字段中的每个 Struct 元素都遵循为该字段定义的 Struct Schema。 |
必须设置 max_capacity。 | 它限制每个 Entity 可在 StructArray 字段中存储的 Struct 元素数量。 |
| 只允许使用支持的子字段类型。 | 使用 StructArray 支持的 scalar 和 vector 子字段类型。不要定义 JSON、Geometry、Text、Timestamptz、SparseFloatVector,或嵌套的 Struct / Array 子字段。 |
| vector 子字段需要先创建 index 才能搜索。 | 在运行 vector search 前,请在 chunks[emb_list_vector] 或 chunks[emb] 等路径上创建 index。 |
| 一个 vector 子字段对应一个 index。 | 如果你同时需要 EmbeddingList search 和 element-level search,请创建两个独立的 vector 子字段。 |
| 已有 StructArray 子字段是固定的。 | 创建 StructArray 字段后,不要预期还能向同一个 StructArray 字段添加更多子字段。 |
| Struct 内不支持 Function。 | 不要为 StructArray 字段内的字段或子字段定义 function。 |
| scalar 子字段应匹配 filter 需求。 | 仅在之后需要 filter、group 或 output 时,才添加 section、quality_score 或 has_code 等字段。 |
常见错误
-
将
DataType.STRUCT创建为顶层 Collection field,而不是将其用作 Array field 的元素类型。 -
忘记在 StructArray field 上设置
max_capacity。 -
定义不支持的 subfield 类型,例如 JSON、Geometry、Text、Timestamptz、SparseFloatVector、嵌套 Array、嵌套 Struct 或 Array-of-Struct。
-
使用
String作为 subfield 类型。请使用VARCHAR并设置max_length。 -
将同一个 vector subfield 同时用于 EmbeddingList search 和 element-level search。
-
只添加 vector subfield,而忘记添加过滤所需的 scalar subfield,例如
section、quality_score或has_code。 -
将 vector subfield 当作
$[...]scalar predicate 输入。vector subfield 用于 vector search,scalar subfield 用于 scalar predicate。 -
假设创建 field 后仍可向现有 StructArray field 添加新的 subfield。
-
使用
chunks.emb或chunks.emb_list_vector,而不是必需的路径语法chunks[emb]或chunks[emb_list_vector]。 -
认为 nullable StructArray 行为在所有目标版本中都可用。
Next steps
-
要将嵌套数据插入 StructArray 字段,请阅读 Insert Data into StructArray Fields。
-
要创建向量和标量 Index,请阅读 Index StructArray Fields。
-
要搜索 StructArray 的向量子字段,请阅读 Basic Vector Search with StructArray。
-
要了解支持的数据类型、nullable 行为和特定版本限制,请阅读 StructArray Limits。