hibernate-search - 如果条件为真则排除文档

标签 hibernate-search

我在一个实体中有三个字段:

  1. 机构名称En
  2. IsTelPublishDa
  3. 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/

相关文章:

sql - hibernate 搜索、实体和 SQL View

java - 为每个子类创建单独的 hibernate 搜索索引

hibernate-search - 休眠搜索土耳其语字符

hibernate - 在 hibernate 搜索中禁用增强功能[通过 hibernate 搜索在elasticsearch中的映射索引中出现问题]

java - Hibernate-Search @IndexedEmbedded with HashMap,如何在索引中包含键集

mysql - 何时使用 Lucene/Hibernate Search

java - Hibernate 搜索前缀

java - 尝试加载 infinispan 配置文件时出现 FileNotFound 异常

java - 无法将 org.hibernate.search.hcore.impl.HibernateSearchIntegrator 转换为 org.hibernate.integrator.spi.Integrator

java - IndexedEmbedded List - 在字段名称中添加元素索引