深入理解 Amazon OpenSearch 中的 span 查询
有效阅读仅保存在当前浏览器,用于「为你」推荐;暂停或清除记录。
DataHot 速览
AWS 官方博客讲解 Amazon OpenSearch Service 中 span 查询的工作原理:当 match_phrase 的 slop 参数不足以精确表达词项位置关系时,span_near、span_term 等查询可以组合出严格的结构约束。文中以法律检索、合规、专利与合同分析等场景为例,并给出创建索引、写入文档和查询验证的完整示例,说明 slop 是编辑距离匹配,会导致非预期的跨词匹配。
原收录理由(待核验):面向检索与搜索基础设施从业者的第一方技术实践,讲清了关键词项位置约束的机制与边界,对做 Text-to-SQL 以外的检索增强、文档合规检索的团队有直接参考价值。
译文
AI 逐段翻译Amazon OpenSearch Service 是一项完全托管的服务,用于在 AWS 云中部署、扩展和运行 OpenSearch。OpenSearch 是一套用于搜索、分析和可观测性的开源软件套件,基于 Apache License V2.0 许可。在 OpenSearch 查询类型中,span 查询让您可以精确控制词项在文档中出现的位置以及它们之间的相互关系。大多数应用通过 match 和 phrase 查询就能获得良好的结果,但某些工作负载需要精确的词项位置,而更简单的查询无法表达。这些包括法律检索、监管合规、科学和专利检索以及合同分析。Span 查询填补了这一空白。
在本文中,您将了解 span 查询的工作原理、何时应使用它们而不是 phrase 查询,以及如何组合它们以对文本表达精确的结构约束。
当 phrase 查询力有不逮时
phrase 查询按顺序匹配连续的词项序列。match_phrase 查询接受一个 slop 参数,该参数通过允许词项之间发生一定数量的位置交换来放宽这一约束。用户搜索“star wars iv”时,期望找到电影“Star Wars: Episode IV — A New Hope”。然而,由于中间插入了“Episode”一词,确切的短语并未出现在标题中。将 slop 设置为 1 可让 OpenSearch 交换一个词项位置并找到匹配。
为了探究这一点,创建一个包含单个 text 字段的索引:
PUT term_order
{
"mappings": {
"properties": {
"title": {"type": "text"}
}
}
}索引两个文档:
POST term_order/_doc/1
{"title": "Star Wars: Episode IV - A New Hope"}
POST term_order/_doc/2
{"title": "Hope for Star Wars: The Prequel Series"}一个针对“star wars iv”的 match_phrase 查询,设置 slop: 1,会匹配第一个文档。将查询改为“star wars hope”,设置 slop: 4,则该查询会匹配两个文档:
GET term_order/_search
{
"query": {
"match_phrase": {
"title": {
"query": "star wars hope",
"slop": 4
}
}
}
}对“Hope for Star Wars: The Prequel Series”的匹配是意料之外的。该文档中词项的顺序与查询不同。Phrase slop 执行编辑距离匹配,在编辑窗口内交换词项,而不考虑顺序。当您需要强制词项顺序、词项在字段中的位置或词项之间的结构关系时,phrase 查询缺乏这种表达能力。
Span 查询能提供什么
Span 查询是复合查询,让您可以精确控制词项相对于彼此的位置。Span 查询只能包含其他 span 查询。您不能在同一个复合表达式中将 span 查询与非 span 查询混用。OpenSearch 支持多种 span 查询类型:
- span_term:匹配单个词项。这通常是复合 span 查询的叶子节点。
- span_multi:包装一个多词项查询(prefix、regex、wildcard),以便在 span 查询内部使用。
- span_first:匹配字段开头指定位置数以内的 span。
- span_near:在指定的
slop内匹配一组 span 子句,类似于match_phrase,但作用于 span。 - span_not:从 span 匹配中排除特定词项。
- span_or:合并多个 span 子句。
- span_field_masking:使用来自另一个字段的
span_term,并遮蔽为以主字段出现。 - span_containing:匹配包含其他 span 的 span。
- span_within:匹配被其他 span 包含的 span。
span_within是span_containing的镜像。
所有 span 查询都接受一个 in_order 参数,该参数控制子 span 是否必须按查询子句的顺序出现。
将词项锚定到某个位置
要在索引中查找“A New Hope”,您可以要求“star”出现在标题开头,并且“hope”出现在其后 12 个词项以内:
GET term_order/_search
{
"query": {
"span_near": {
"clauses": [
{
"span_first": {
"match": {"span_term": {"title": "star"}},
"end": 2
}
},
{"span_term": {"title": {"value": "hope"}}}
],
"slop": 12,
"in_order": true
}
}
}此查询仅匹配“Star Wars: Episode IV — A New Hope”。span_first 子句要求“star”出现在标题的前两个位置内。外层的 span_near 则要求“hope”在 12 个位置以内、按指定顺序出现。第二个文档不匹配,因为“star”不在标题开头。
Span 之中的 span
借助 span_containing 和 span_within,您可以通过将一个 span 匹配于另一个 span 之内来表达结构约束。两者都接受一个 big 子句和一个 little 子句:little span 必须被 big span 包含。区别在于查询返回哪个 span。span_containing 返回 big 匹配,而 span_within 返回 little 匹配。
例如,要查找短语“episode iv”出现在同时包含“star”和“hope”的 span 内的文档:
GET term_order/_search
{
"query": {
"span_containing": {
"little": {
"span_near": {
"clauses": [
{"span_term": {"title": {"value": "episode"}}},
{"span_term": {"title": {"value": "iv"}}}
],
"slop": 0,
"in_order": true
}
},
"big": {
"span_near": {
"clauses": [
{"span_term": {"title": {"value": "star"}}},
{"span_term": {"title": {"value": "hope"}}}
],
"slop": 12,
"in_order": false
}
}
}
}
}其中 little 子句将“episode iv”作为精确短语匹配(slop 为 0,in_order 为 true)。big 子句匹配一个包含“star”和“hope”且二者相距 12 个词项以内、顺序不限的 span。然后 span_containing 查询要求 little 短语落在 big 匹配之内。只有“Star Wars: Episode IV — A New Hope”同时满足这两个约束。
何时使用 span 查询
当您需要表达 phrase 查询无法表达的约束时,span 查询都很有用。在法律和监管检索中,法规和合同通常要求特定短语出现在邻近位置。一个例子是查找“force majeure”出现在“termination”五个词项以内的文档。Span 查询为您提供表达该要求的精确控制。
在专利和科学检索中,权利要求和论文经常要求词项相对于彼此出现在特定的结构位置。必须强制执行精确词项位置以满足监管定义的合规和审计工作流同样受益于这种精确性。更一般地说,当您的文本没有显式的结构化模型,但您需要表达有关词项在字段中出现位置的约束时,span 查询提供了一种查询时的替代方案,而无需重塑您的数据。
结论
Span 查询以简单性换取精确性。Span 查询比 phrase 查询更冗长,并且需要仔细组合。作为回报,您可以使用它们来表达 phrase 查询无法表达的约束:精确顺序、字段内的位置以及包含关系。对于词项位置具有含义的应用,span 查询是合适的工具。
更多信息,请参阅 OpenSearch span 查询文档 以及 Amazon OpenSearch Service 文档。
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏