跳到主要内容
版本:v3.0.x

Text Field

在 AI search 应用中,vector search 可以帮助你找到语义相似的 Entity,但应用通常还需要每个匹配结果背后的原始源文本。LLM 或 agent 可以将该文本用作上下文,用于阅读、引用、总结,或将结果包含在 prompt 中。

Milvus 提供 TEXT 标量字段类型,用于直接随 Entity 存储较长的源文本。典型值包括段落、长文档、文章正文、工单和日志。与需要固定 max_lengthVARCHAR 不同,TEXT 不要求你在 Collection Schema 中设置最大字节长度。

要定义 TEXT 字段,请将 datatype 设置为 DataType.TEXT

此功能需要 Storage V3。有关启用说明和兼容性注意事项,请参阅 Storage V3

如果 Storage V3 处于禁用状态,Milvus 会拒绝包含 TEXT 字段的 Collection Schema。

Python
schema.add_field(
field_name="content",
datatype=DataType.TEXT,
)

定义字段后,每个 Entity 都可以在该字段中包含一个字符串值。你可以像插入其他标量字段一样插入 TEXT 值,并通过在 output_fields 中列出该字段,从 query 或 search 结果中返回这些值。

TEXT 字段支持 NULL 值。要启用此功能,请将 nullable 设置为 True。详情请参阅 Nullable Field

Limits

  • TEXT 字段不能作为 primary field。Primary field 支持 INT64VARCHAR
  • 在 Milvus 3.0.0 中,TEXT 字段不支持 PHRASE_MATCH
  • 在 Milvus 3.0.0 中,TEXT 字段不支持默认值。
  • 在 Milvus 3.0.0 中,外部 Collection 不支持 TEXT 字段。
  • 在 Milvus 3.0.0 中,TEXT 字段不支持 scalar index。
  • TEXT 不适用于常规元数据过滤。如果你需要基于短字符串元数据进行过滤,且字段值满足 VARCHAR 长度限制,请使用 VARCHAR

选择 TEXT 或 VARCHAR

TEXTVARCHAR 都用于存储字符串值,但适用于不同的应用需求。对于用于标识、分类或过滤 Entity 的短小、有界元数据,请使用 VARCHAR。对于较长的源内容,如果需要为 LLM 或 agent 提供足够上下文来阅读、引用、总结或构建 prompt,请使用 TEXT

方面VARCHARTEXT
最适合用于标识、分类或过滤 Entity 的短元数据,例如 titletagcategoryexternal_id用于 LLM 或 agent 工作流的较长源内容,例如 contentpassagearticle_bodylog_message
长度设置需要 max_length,用于定义该字段可存储的最大字节数。最大值为 65,535 字节。如果某个值可能超过此限制,请使用 TEXT不需要 max_length,因此 Schema 无需为文本值设置固定字节限制。
存储行为在字段配置的 max_length 范围内存储每个值。对较大的文本值使用自动存储选择。详情请参阅 Milvus 如何存储大型 TEXT 值
Primary field 支持可用作 Primary field。不能用作 Primary field。
过滤用于需要出现在 Filter 表达式中的短字符串元数据,例如 category == "news"tag in ["ai", "database"]不适合用于常规元数据过滤。

有关 VARCHAR 字段的详细信息,请参阅 VarChar Field

How Milvus stores large TEXT values

展开查看工作原理

插入 Entity 时,你为 TEXT 字段提供的字符串就是 TEXT 值。Milvus 会将该值的大小与 dataNode.text.inlineThreshold 进行比较。该阈值默认为 65,536 字节,然后 Milvus 会选择以下两种内部存储路径之一。

Large text storage

  • Inline storage:如果 TEXT 值小于 dataNode.text.inlineThreshold,Milvus 会将原始文本值直接存储在 TEXT 字段数据中。
  • LOB storage:如果 TEXT 值大于或等于 dataNode.text.inlineThreshold,Milvus 会将该值视为大对象,并将原始文本单独存储在对象存储中,例如 MinIO。TEXT 字段数据会存储一个指向该独立文本的内部引用。当查询或搜索结果请求 TEXT 字段时,Milvus 会使用该引用检索并返回原始文本。

这种存储选择是内部行为。无论 Milvus 使用哪种存储路径,你插入、查询和搜索 TEXT 字段的方式都相同。如需调整阈值,或调整相关的存储、Compaction 和垃圾回收行为,请参阅 dataNode-related ConfigurationsdataCoord-related Configurations

如果你的部署使用对象存储,大型 TEXT 值可能会以 Milvus 管理对象的形式出现在 lobs/... 等路径下。这些对象属于实现细节,不应手动移动、复制或删除。删除 Entity、删除 Partition 或执行 Compaction 后,只有在 Milvus 垃圾回收经过安全窗口并移除未引用的大对象数据之后,对象存储用量才可能下降。

TEXT 的一个常见用途是结合 BM25 进行 Full Text Search。在这种模式下,TEXT 字段存储原始源内容,BM25 会分析文本并生成 sparse vectors,用于对基于关键词的匹配结果进行排序。随后,搜索结果可以返回匹配的 TEXT 值,作为 LLM 或 Agent 工作流的上下文。以下示例展示如何将 TEXT 字段用作 BM25 的输入字段。如需了解 Full Text Search 的概念和查询选项,请参阅 Full Text Search

Step 1:创建包含 TEXT 字段的 Collection

以下示例创建一个 Collection,其中包含用于源内容的 TEXT 字段,以及用于存储 BM25 生成的稀疏向量的 sparse vector 字段。BM25 function 会将 content 中经过 Analyzer 分词的文本转换为稀疏向量,并存储在 sparse 中。

对于 BM25 Full Text Search,输入 TEXT 字段必须设置 enable_analyzer=True

Python
from pymilvus import DataType, Function, FunctionType, MilvusClient

client = MilvusClient(uri="http://localhost:19530")
COLLECTION_NAME = "text_bm25_collection"

if client.has_collection(COLLECTION_NAME):
client.drop_collection(COLLECTION_NAME)

schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(
field_name="content",
datatype=DataType.TEXT,
enable_analyzer=True,
)
schema.add_field(field_name="sparse", datatype=DataType.SPARSE_FLOAT_VECTOR)

bm25_function = Function(
name="content_bm25",
input_field_names=["content"],
output_field_names=["sparse"],
function_type=FunctionType.BM25,
)
schema.add_function(bm25_function)

Step 2: Create a sparse vector index

为 BM25 function 生成的 sparse vector 字段创建 Index。metric type 必须设置为 BM25

Python
index_params = client.prepare_index_params()
index_params.add_index(
field_name="sparse",
index_type="SPARSE_INVERTED_INDEX",
metric_type="BM25",
params={
"inverted_index_algo": "DAAT_MAXSCORE",
"bm25_k1": 1.2,
"bm25_b": 0.75,
},
)

client.create_collection(
collection_name=COLLECTION_NAME,
schema=schema,
index_params=index_params,
)

Step 3: Insert TEXT data

将文本直接插入 TEXT 字段。不要为 sparse 字段提供值。Milvus 会在内部对 content 应用 BM25 function 来生成 sparse vectors。

Python
data = [
{
"id": 1,
"content": "Milvus stores vector embeddings and scalar fields in collections. It supports vector search, full text search, and metadata filtering for retrieval applications.",
},
{
"id": 2,
"content": "Long documents are often split into passages before embedding. Store each passage in a TEXT field so search results can return the source text.",
},
{
"id": 3,
"content": "Operational logs and support tickets often contain long natural-language text. TEXT fields can store these values without a fixed max_length setting.",
},
]

client.insert(collection_name=COLLECTION_NAME, data=data)
client.load_collection(collection_name=COLLECTION_NAME)

使用原始查询文本作为搜索数据,并针对 sparse vector 字段进行搜索。Milvus 会将查询文本转换为 sparse vector,使用 BM25 对匹配结果进行排序,并在 output_fields 中返回请求的 TEXT 字段。

Python
results = client.search(
collection_name=COLLECTION_NAME,
data=["how does Milvus store source text for retrieval"],
anns_field="sparse",
limit=2,
output_fields=["content"],
)

Step 5: 读取返回的 TEXT 值

每个 search hit 都包含 BM25 分数和原始 TEXT 值。

Python
for hit in results[0]:
print(f"id: {hit['id']}, score: {hit['distance']}")
print(hit["entity"]["content"])

有关 BM25 functions、sparse vector indexes 以及 Full Text Search 查询语法的更多信息,请参阅 Full Text Search