给定一个包含此文本的文档,索引在名为 Content 的字段中:

The dish ran away with the spoon.

以下查询无法匹配该文档:
+Content:dish +(-Content:xyz)   <-- no results!

我希望查询被视为 必须包括“dish”,不能包括“xyz” 。失败的是“不能”的部分。

我知道 +- 组合看起来很有趣,但在语法上它应该是正确的,尤其是考虑到以下变体都有效:
+Content:dish +(-Content:xyz +Content:spoon)   <-- this works
+Content:dish -Content:xyz                     <-- this works

那么为什么 +(-Content:xyz) 不起作用呢?这是设计使然,还是错误,还是我只是遗漏了什么?我正在使用 Lucene.Net,但我认为常规 Lucene 的行为是相同的。

最佳答案

Lucene 并不像 SQL 数据库那样从所有事物的完整 View 开始。 Lucene 从没有匹配的文档开始,并根据搜索的子句查找内容。这就是为什么:

-Content:xyz

靠它自己并不真正起作用。它知道不要引入 content:xyz,但没有得到任何匹配的文件。您的查询也是如此,因为它位于子查询中。
-Content:xyz 首先被评估,它自己没有文档。那么你有,有效地
+Content:dish +(no documents)

- 视为 AND NOT 而不是简单的 NOT 是很有用的(尽管不要认为这意味着 +/- 和 AND/OR/NOT 语法必须直接相互映射)。

如果您希望能够执行这样一个单独的否定查询,您需要首先引入所有文档。 MatchAllDocsQuery 是实现这一目标的最佳方式,例如:
BooleanQuery query = new BooleanQuery();
query.add(new BooleanClause(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD));
query.add(new BooleanClause(new TermQuery(new Term("Content","xyz")), BooleanClause.Occur.MUST_NOT));

将等效于 SQL 样式查询,仅对 WHERE 子句进行否定。

当然,在您列出的情况下,这并不是真正必要的:
+Content:dish -Content:xyz

完全够用。

关于Lucene 查询失败,混合 MUST/MUST_NOT,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16089831/

10-10 21:42
查看更多