SpanNotQuery 存在的意义就是:
在"词的位置"这一更细粒度上做布尔运算,而不仅仅在"文档"级别做 AND/OR/NOT。
它让 Lucene 从"文档检索"升级到"短语/区间检索",满足更复杂的业务需求。 啥意思?
把它拆成三层,你就明白了:
- 传统 BooleanQuery(文档级)
只能告诉你:
"这篇文档里同时有 apple 和 pie。"
至于这两个词在文档里相距多远、谁先谁后,它完全不知道。
举例:
-
文档 A:"I like apple and pie." → 命中
-
文档 B:"apple ...(隔 500 词)... pie." → 也命中
你无法区分 A、B 的差异。
- SpanQuery(区间级)
把"文档"再往下拆成"词的位置区间",于是可以问:
"在这篇文档里,apple 和 pie 挨得不超过 3 个词。"
这就是 SpanNearQuery。
此时:
-
文档 A 会给出一段区间 `[apple, pie]`;
-
文档 B 因为距离太远,没有任何区间满足,文档就不被命中。
- SpanNotQuery(区间级布尔运算)
在区间上再做"减法":
"先把 所有出现 apple 的区间 拿出来,但如果这段 apple 被 'apple ... pie 且距离≤3' 的区间罩住,就整段扔掉。"
结果:
-
文档 A 的 apple 被"剪掉",于是这篇文档不会被返回;
-
文档 C:"I like apple cake." 里的 apple 没被罩住,就被保留,文档返回。
一句话类比
-
BooleanQuery 像"整本书"级别的标签:这本书贴了"apple"和"pie"两张标签。
-
SpanQuery 像"页码"级别的标签:第 12 页第 3 行到第 5 行是 "apple pie"。
-
SpanNotQuery 像用剪刀把某几页里不想保留的段落裁掉,只把剩余段落还给读者。
因此,"升级"指的是:
从 "整本书要不要" → "把书里具体几行裁掉或保留",粒度细得多,能满足"邻近/排除/精准高亮"等更复杂的搜索需求。