Lucene查询失败,混合MUST / MUST_NOT

时间:2013-04-18 17:48:08

标签: lucene lucene.net

给定一个包含此文本的文档,在名为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表现相同。

1 个答案:

答案 0 :(得分:9)

Lucene并不是以SQL数据库的全部视图开始的。 Lucene首先没有匹配的文档,并根据搜索的子句查找内容。这就是原因:

-Content:xyz

它本身并没有真正起作用。它知道不引入内容: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

完全足够。