【问题标题】:Lucene query fails with mixed MUST/MUST_NOTLucene 查询因混合 MUST/MUST_NOT 而失败
【发布时间】:2013-04-11 23:22:26
【问题描述】:

给定一个包含此文本的文档,索引在名为 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 lucene.net


    【解决方案1】:

    Lucene 并不是从一个完整的视图开始的,比如 SQL 数据库。 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));
    

    相当于只对 WHERE 子句进行否定的 SQL 样式查询。

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

    +Content:dish -Content:xyz
    

    完全够用了。

    【讨论】:

    • 现在对我来说很有意义。谢谢!
    • 仅供参考,MatchAllDocsQuery 的字符串表示形式是 *:*。我上面的示例应更改为以下内容才能正常工作:+Content:dish +(+*:* -Content:xyz)
    • @Keith 好吧,不,它应该改为等效的:Content:dish -Content:xyz,但是,是的,这会起作用(慢慢地)。不记得对*:* 的支持是什么样的(是否只是在 Solr 中,哪些版本支持它,是否被 .Net impl 支持)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多