全文检索
全文检索通过匹配文本内容来查找 Document,使用 BM25 相关性评分进行排序。支持自然语言查询、精确短语匹配和布尔运算符。
前提条件
本指南假设你已经打开了一个 Collection,并准备好了一个 collection 对象。
定义全文检索字段
要对字段启用全文检索,需要添加一个 FieldSchema 并将 FtsIndexParam 作为其 index_param。该字段的数据类型必须为 STRING。
import zvec
fts_field = zvec.FieldSchema(
name="content",
data_type=zvec.DataType.STRING,
nullable=False,
index_param=zvec.FtsIndexParam(
tokenizer_name="jieba", # 使用 Jieba 中文分词器
),
)FtsIndexParam 参数
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
tokenizer_name | str | "standard" | 可选 "standard"、"ngram"、"whitespace" 或 "jieba"。详见分词器。 |
filters | list[str] | ["lowercase"] | 分词后按顺序应用的 Token 过滤器。详见 Token 过滤器。 |
extra_params | str | "" | 分词器和过滤器特定配置的 JSON 字符串。详见各分词器和 Token 过滤器的配置说明。 |
Zvec 支持纯全文检索的 Collection — 可以创建仅包含文本字段、不包含向量字段的 Collection。
执行全文检索
Zvec 提供两种全文检索的查询模式,均通过 Query 中的 Fts 对象使用:
- Match String — 自然语言输入,自动分词
- Query String — 支持布尔运算符的高级表达式语法
Match String
使用 match_string 进行自然语言查询。输入为纯文本,无需任何特殊语法或转义。它会使用该字段配置的分词器进行分词,Token 之间使用默认运算符(默认为 OR)组合。
from zvec.model.param.query import Fts, Query
result = collection.query(
queries=Query(
field_name="content",
fts=Fts(match_string="机器学习"),
),
topk=5,
)
print(result)使用默认的 OR 运算符时,将返回包含"机器"或"学习"(或两者都包含)的 Document,按 BM25 相关性评分排序。
Query String
使用 query_string 进行高级查询,支持显式布尔运算符、必需/排除词项和精确短语匹配。
from zvec.model.param.query import Fts, Query
result = collection.query(
queries=Query(
field_name="content",
fts=Fts(query_string='+学习 -神经网络 "向量搜索"'),
),
topk=5,
)
print(result)使用默认的 OR 运算符时,文档必须匹配“学习”,并排除匹配“神经网络”的文档。“向量搜索”是可选短语,命中时会计入相关性评分。
query_string 和 match_string 互斥 — 每个 Fts 对象中必须且只能提供其中一个。
查询语法参考
以下运算符可在 query_string 表达式中使用:
| 语法 | 含义 | 示例 |
|---|---|---|
term | 匹配单个词项 | vector |
"phrase" | 匹配精确短语(词序和相邻性) | "machine learning" |
+term | 词项必须出现在 Document 中 | +vector |
-term | 词项不得出现在 Document 中 | -slow |
a AND b | 两个词项都必须匹配 | vector AND search |
a OR b | 任一词项匹配即可 | vector OR embedding |
a NOT b | 匹配 a 但排除匹配 b 的 Document | learning NOT deep |
(expr) | 分组子表达式 | (vector OR embedding) AND search |
+(expr) | 分组必须匹配 | +(vector OR embedding) |
-(expr) | 分组不得匹配 | -(slow AND outdated) |
运算符优先级:AND / NOT 的绑定优先级高于 OR。没有显式运算符的相邻词项使用 default_operator 设置进行组合(默认为 OR)。
对于混合使用多种运算符的复杂查询,建议使用 () 显式分组以避免非预期结果。
不支持前置否定 — NOT term 和单独的 -term 都需要至少一个肯定词项。请使用 a NOT b 或将 -term 与肯定词项组合使用(例如 a -b)。
查询参数
| 参数 | 描述 |
|---|---|
topk | 返回评分最高的 Document 数量。 |
filter | 可选的类 SQL 布尔表达式,用于限制结果。详见条件过滤。 |
output_fields | 可选的标量字段名称列表,用于指定结果中包含的字段。如果省略,返回所有标量字段。 |
默认运算符
默认情况下,match_string 和 query_string 中相邻的裸词项使用 OR 组合。要改为 AND,可通过 param 字段传入 FtsQueryParam:
import zvec
from zvec.model.param.query import Fts, Query
result = collection.query(
queries=Query(
field_name="content",
fts=Fts(match_string="机器学习"),
param=zvec.FtsQueryParam(default_operator="AND"),
),
topk=5,
)设置 default_operator="AND" 后,仅返回同时包含"机器"和"学习"的 Document。
query_string 中的显式运算符(AND、OR、+、-)不受 default_operator 影响 — 它仅控制相邻裸词项的组合方式。
结合标量过滤
可以将全文检索与标量过滤结合使用以缩小结果范围:
from zvec.model.param.query import Fts, Query
result = collection.query(
queries=Query(
field_name="content",
fts=Fts(match_string="机器学习"),
),
filter="category = '技术'",
topk=5,
)全文检索和向量检索在单个查询路线中互斥。同一个 Query / ZVecQuery 不应同时设置 fts 和 vector / id;如需结合两者,请使用多条查询路线配合重排序,或分别执行查询后在应用层合并结果。
分词器
Zvec 提供四种内置分词器,通过 FtsIndexParam 为每个字段单独配置。
| 分词器 | 名称 | 描述 |
|---|---|---|
| Standard | "standard" | 实现 Unicode UAX #29 词边界规则,行为类似 Elasticsearch standard tokenizer。适用于大多数拉丁字母语言。(默认) |
| N-gram | "ngram" | 将文本切成相互重叠的字符片段,用于匹配词的一部分。 |
| Whitespace | "whitespace" | 仅按空白字符(空格、制表符、换行符)拆分文本。保留 Token 内的标点符号。 |
| Jieba | "jieba" | 基于 cppjieba 的中文分词。支持中英文混合文本。 |
Standard 分词器
默认分词器。它实现了 Unicode UAX #29 词边界规则,行为类似 Elasticsearch standard tokenizer。对于 CJK 表意文字,standard 会输出单字 Token;如果需要中文词级检索,通常应使用 jieba。
zvec.FtsIndexParam(tokenizer_name="standard", filters=["lowercase"])配置(通过 extra_params JSON):
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
max_token_length | int | 255 | 按 Unicode 码点计数的长度阈值。分词器按此阈值切分长词,取值范围为 1 至 1,048,576。 |
N-gram 分词器
默认配置下,ngram 将 zvec 切为 zv、ve 和 ec。因此,搜索 ve 可以命中包含 zvec 的文档。
extra_params 参数 | 默认值 | 说明 |
|---|---|---|
ngram_min | 2 | 片段的最小长度,按 Unicode 码点计数,必须为正整数。 |
ngram_max | 2 | 片段的最大长度,可设为 ngram_min 或 ngram_min + 1。 |
token_chars | [] | 空数组保留所有有效的 UTF-8 字符。可指定要保留的类别,其余字符作为分隔符。可选 letter、digit、whitespace、punctuation 和 symbol。 |
Whitespace 分词器
仅在空白字符处拆分文本。适用于需要保留 Token 内标点符号的场景。
zvec.FtsIndexParam(tokenizer_name="whitespace", filters=["lowercase"])Jieba 分词器
需要按词检索中文或中英混合文本时,选择 jieba。分词器默认使用原生库内置的词典和 HMM 模型。
zvec.FtsIndexParam(
tokenizer_name="jieba",
filters=["lowercase"],
)配置(通过 extra_params JSON):
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
jieba_dict_dir | str | — | 存放外部主词典 jieba.dict.utf8 和 HMM 模型 hmm_model.utf8 的目录。 |
user_dict_path | str | — | 用户词典文件路径,用于在当前字段选用的主词典上补充业务词汇。适用于 search、mix 和 full 模式。 |
cut_mode | str | "search" | 分词模式:"search"(细粒度,推荐用于搜索)、"mix"、"full" 或 "hmm"。各模式详情请参阅 cppjieba 文档。 |
Jieba 优先使用字段的 jieba_dict_dir,其次使用环境变量 ZVEC_JIEBA_DICT_DIR。两者均未设置或为空时,使用内置资源。如果指定了外部目录,而当前模式所需的文件不可读,分词器会初始化失败。
Token 过滤器
Token 过滤器在分词后按 filters 数组顺序应用。索引构建和查询使用同一套过滤器配置。
| 过滤器 | 描述 |
|---|---|
"lowercase" | 将 Token 转换为 Unicode 小写。 |
"ascii_folding" | 将 Unicode 字符折叠为 ASCII 等价形式。 |
"stemmer" | 使用 Snowball 词干提取器归一化词形。 |
英文文本通常可以使用 lowercase、stemmer 组合,让大小写和词形变化不影响匹配。类英文文本或包含重音符号的文本还可以加入 ascii_folding,以获得重音无关匹配。
Lowercase 过滤器
"lowercase" 将所有 Token 转换为 Unicode 小写。
ASCII Folding 过滤器
"ascii_folding" 将 Unicode 字符折叠为 ASCII 等价形式。
Stemmer 过滤器
"stemmer" 使用 Snowball 词干提取器归一化词形,默认语言为 "english"。
zvec.FtsIndexParam(
tokenizer_name="standard",
filters=["lowercase", "stemmer"],
extra_params='{"stemmer_lang": "english"}',
)Stemmer 配置(通过 extra_params JSON):
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
stemmer_lang | str | "english" | Snowball 语言或算法名称。例如设置为 "porter" 可获得接近 Elasticsearch 默认英文 stemmer 的行为。 |
约束
- 全文检索和向量检索在单个查询路线中互斥 — 同一个
Query/ZVecQuery不应同时设置fts和vector/id。 query_string和match_string在单个Fts对象中互斥。- 请在创建 Collection 时定义文本字段。Schema 变更接口不支持添加、修改或删除全文检索字段。要在已有字符串字段上创建或删除全文索引,可使用
create_index()或drop_index()。 - 不支持前置否定(
NOT term或单独的-term)— 至少需要一个肯定词项。