如何在Hibernate Search中使用布尔运算符

我正在学习Hibernate Search Query DSL ,我不知道如何使用AND或OR等布尔参数构造查询。

例如,假设我想返回firstName值为“bill”或“bob”的所有人员记录。

在hibernate文档之后,一个示例使用bool()方法w /两个子查询,例如:

 QueryBuilder b = fts.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get(); Query luceneQuery = b.bool() .should(b.keyword().onField("firstName").matching("bill").createQuery()) .should(b.keyword().onField("firstName").matching("bob").createQuery()) .createQuery(); logger.debug("query 1:{}", luceneQuery.toString()); 

这最终产生了我想要的lucene查询,但这是在hibernate搜索中使用布尔逻辑的正确方法吗? “should()”是否等同于“OR”(类似地,“must()”对应于“AND”)?

此外,以这种方式编写查询感觉很麻烦。 例如,如果我有一个firstNames的集合来匹配怎么办? 这种类型的查询首先是DSL的良好匹配吗?

是的你的例子是正确的。 由于Lucene API和文档中的名称,因此调用布尔运算符而不是OR ,因为它更合适:它不仅影响布尔决策,而且还影响结果的评分。

例如,如果您搜索“菲亚特品牌”或“蓝色”的汽车,那么品牌菲亚特和蓝色的汽车也将被退回并且得分高于蓝色但不是菲亚特的汽车。

它可能会感觉很麻烦,因为它是程序化的,并提供了许多详细的选项。 更简单的替代方法是为查询使用简单字符串,并使用QueryParser创建查询。 通常,解析器对于解析用户输入很有用,程序化的解析器更容易处理明确定义的字段; 例如,如果你有你提到的集合,很容易在for循环中构建它。

为了回答你的第二个问题:

例如,如果我有一个firstNames的集合来匹配怎么办?

我不是专家,但根据(结尾的第三个例子) 5.1.2.1。 在Hibernate Search Documentation中的 关键字查询 ,您应该能够像这样构建查询:

 Collection namesCollection = getNames(); // Contains "billy" and "bob", for example StringBuilder names = new StringBuilder(100); for(String name : namesCollection) { names.append(name).append(" "); // Never mind the space at the end of the resulting string. } QueryBuilder b = fts.getSearchFactory().buildQueryBuilder().forEntity(Person.class).get(); Query luceneQuery = b.bool() .should( // Searches for multiple possible values in the same field b.keyword().onField("firstName").matching( sb.toString() ).createQuery() ) .must(b.keyword().onField("lastName").matching("thornton").createQuery()) .createQuery(); 

因此, Person有( firstName 最好是 “billy”或“bob”)和( lastName =“thornton”),虽然我认为它不会给予’Billy Bob Thornton更高的分数; – )。

您也可以使用BooleanQuery 。 我更喜欢这个因为你可以在列表的循环中使用它。

  org.hibernate.search.FullTextQuery hibque = null; org.apache.lucene.search.BooleanQuery bquery = new BooleanQuery(); QueryBuilder qb = fulltextsession.getSearchFactory().buildQueryBuilder() .forEntity(entity.getClass()).get(); for (String keyword : list) { bquery.add(qb.keyword().wildcard().onField(entityColumn).matching(keyword) .createQuery() , BooleanClause.Occur.SHOULD); } if (!filterColumn.equals("") && !filterValue.equals("")) { bquery.add(qb.keyword().wildcard().onField(column).matching(value).createQuery() , BooleanClause.Occur.MUST); } hibque = fulltextsession.createFullTextQuery(bquery, entity.getClass()); int num = hibque.getResultSize(); 

我一直在寻找同样的问题,并且提出的问题有些不同。 我正在寻找一个真正的OR结。 如果结果没有通过这两个表达中的任何一个,但得分较低,那应该对我不起作用。 我想完全省略这些结果。 但是,您可以创建一个实际的布尔OR表达式,使用一个单独的布尔表达式来禁用评分:

 val booleanQuery = cb.bool(); val packSizeSubQuery = cb.bool(); packSizes.stream().map(packSize -> cb.phrase() .onField(LUCENE_FIELD_PACK_SIZES) .sentence(packSize.name()) .createQuery()) .forEach(packSizeSubQuery::should); booleanQuery.must(packSizeSubQuery.createQuery()).disableScoring(); fullTextEntityManager.createFullTextQuery(booleanQuery.createQuery(), Product.class) return persistenceQuery.getResultList();