我在一个实体中有三个字段:
- 机构名称En
- IsTelPublishDa
- isTelSecret
我对estinationNameEn进行了模糊搜索。现在,如果字段 IsTelPublishDa 值为 0 或 isTelSecret 值为 1,我想应用条件来排除文档。
我的最终查询是:(+buildingNameEn:kamran~1 +(-IsTelPublishDa:[0 TO 0] -isTelSecret:[1 TO 1]))
但它没有返回结果。
查询代码:
private org.apache.lucene.search.Query excludeDoc(QueryBuilder queryBuilder) {
List<org.apache.lucene.search.Query> queries = new ArrayList<>();
queries.add(queryBuilder.keyword().onField("IsTelPublishDa").matching(0).createQuery());
queries.add(queryBuilder.keyword().onField("isTelSecret").matching(1).createQuery());
BooleanQuery.Builder builder = new BooleanQuery.Builder();
for (Query qu : queries) {
builder.add(qu, BooleanClause.Occur.MUST_NOT);
}
return builder.build();
}
主要方法:
Query fuzzyQuery = queryBuilder.keyword().fuzzy().withEditDistanceUpTo(1).onField("establishmentNameEn").matching(word).createQuery();
luceneQuery.add(fuzzyQuery);
luceneQuery.add(excludeDoc(queryBuilder));
BooleanQuery.Builder builder = new BooleanQuery.Builder();
for (Query qu : luceneQuery) {
builder.add(qu, BooleanClause.Occur.MUST);
}
最佳答案
这永远不会匹配任何内容,因为 bool 查询仅包含否定子句:
BooleanQuery.Builder builder = new BooleanQuery.Builder();
for (Query qu : queries) {
builder.add(qu, BooleanClause.Occur.MUST_NOT);
}
return builder.build();
这很令人困惑,但这就是 Lucene 的工作方式,当您使用 BooleanQuery.Builder
时,您正在使用低级 Lucene API。
解决方案#1
如果您想避免将来出现这种意外,请确保查询中始终包含肯定子句。例如,重构代码以将“MUST_NOT”子句添加到顶级 bool 查询:
// Main code
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(queryBuilder.keyword().fuzzy().withEditDistanceUpTo(1).onField("establishmentNameEn").matching(word).createQuery(), BooleanClause.Occur.MUST);
builder.add(excludedDoc(queryBuilder), BooleanClause.Occur.MUST_NOT);
private org.apache.lucene.search.Query excludedDoc(QueryBuilder queryBuilder) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(queryBuilder.keyword().onField("IsTelPublishDa").matching(0).createQuery(), BooleanClause.Occur.SHOULD);
builder.add(queryBuilder.keyword().onField("isTelSecret").matching(1).createQuery(), BooleanClause.Occur.SHOULD);
return builder.build();
}
解决方案#2
或者,您可以按原样保留代码,但使用 Hibernate Search DSL 而不是 BooleanQuery.Builder
。 Hibernate Search DSL“修复”了 Lucene 的一些最令人困惑的方面,以便此查询将按预期工作(匹配除与子句匹配的文档之外的所有文档):
BooleanJunction<?> booleanJunction = queryBuilder.bool();
for (Query qu : queries) {
booleanJunction.mustNot(qu);
}
return booleanJunction.createQuery();
更多详细信息...
如果你想知道为什么这不起作用......
默认情况下, bool 查询不会匹配任何内容,除非(正)子句与文档匹配,在这种情况下,将根据其他(正或负)子句过滤掉匹配的文档。
因此,在您的情况下,查询不匹配任何内容,然后使用“不得”子句将其过滤掉,因此它仍然不匹配任何内容。
只需添加 MatchAllDocs
子句即可使其按预期工作:
BooleanQuery.Builder builder = new BooleanQuery.Builder();
builder.add(new MatchAllDocsQuery(), BooleanClause.Occur.MUST);
for (Query qu : queries) {
builder.add(qu, BooleanClause.Occur.MUST_NOT);
}
return builder.build();
关于hibernate-search - 如果条件为真则排除文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59824961/