过滤Lucene结果,而不是

过滤Lucene结果,而不是,lucene,Lucene,我试图从查询结果中筛选出许多项 最终结果应仅包含Private设置为false的结果,或者如果为true,则为提供的隐私组的一部分 假设基本查询结果如下 ID Name Private PrivacyGroup 1 Yellow false 2 Red true 1 3 Blue true 2 4 Orange true 1 5 Black false 6 Green true 3 我尝试过各种各样的过滤器

我试图从查询结果中筛选出许多项

最终结果应仅包含Private设置为false的结果,或者如果为true,则为提供的隐私组的一部分

假设基本查询结果如下

ID  Name    Private PrivacyGroup
1   Yellow  false   
2   Red     true    1
3   Blue    true    2
4   Orange  true    1
5   Black   false
6   Green   true    3
我尝试过各种各样的过滤器,但这似乎是一个我认为应该有效的过滤器,但它不是:

BooleanQuery bq = new BooleanQuery();       

BooleanQuery privacyQuery  = new BooleanQuery();
BooleanQuery privacyFinalQuery  = new BooleanQuery();

privacyFinalQuery.add(new TermQuery(new Term("Private", "true")),Occur.MUST);

for(String i : suppliedGroups){
privacyQuery.add(new TermQuery(new Term("PrivacyGroup", i)), Occur.SHOULD);
}

privacyFinalQuery.add(groupQuery, Occur.MUST_NOT);

bq.add(privacyFinalQuery, Occur.MUST_NOT);

return new CachingWrapperFilter(new QueryWrapperFilter(bq));
这导致了

(-(+Private:true -(PrivacyGroup:1 PrivacyGroup:2)))
最终结果是0个结果,我期望:1,2,3,4,5


有什么建议吗?

您的查询完全是否定的,与任何文档都不匹配

您应该添加
MatchAllDocsQuery
作为第一个子句,并通过提供的否定查询对其进行进一步筛选

尝试添加以下行:

bq.add(new MatchAllDocsQuery(), Occur.MUST);

MatchAllDocsQuery
作为纯否定查询的开头,是的。它的表现非常糟糕,但它确实做到了

看起来,按照您陈述问题的相同方式构造查询将导致更简单、更少黑客攻击的实现:

Private设置为false或true是提供的隐私组的一部分

因此,您需要private=false或group=1或group=2,可以更简单地说:

(Private:false PrivacyGroup:1 PrivacyGroup:2)
或者


是的,这是一个非常好的变体,但是BQ经过了适当的优化,并使用
advance
函数跳过了任何查询部分的大的不匹配区域。因此,我无法在没有测试的情况下进行性能差异评估。@Nikolay我不知道lucene中有任何性能优化,这些优化会导致
MatchAllDocsQuery-term
performant之类的查询。你能告诉我该功能的文档吗?一定有比使用matchalldocsquery更好的过滤内容的方法吗?我喜欢过滤方法,因为它保证了一定程度的安全性。如果我在查询过程中犯了错误,我可以保证某些内容不会显示出来。我相信我发布的代码会返回一个合适的过滤器,而不依赖于全部匹配。
BooleanQuery privacyQuery  = new BooleanQuery();

privacyQuery.add(new TermQuery(new Term("Private", "false")),Occur.SHOULD);

for(String i : suppliedGroups){
    privacyQuery.add(new TermQuery(new Term("PrivacyGroup", i)), Occur.SHOULD);
}

return new CachingWrapperFilter(new QueryWrapperFilter(privacyQuery));