Home > Mobile >  BooleanJunction#isEmpty equivalent in Hibernate Search 6 BooleanPredicateClausesStep
BooleanJunction#isEmpty equivalent in Hibernate Search 6 BooleanPredicateClausesStep

Time:06-28

Hibernate Search 5 BooleanJunction has a useful isEmpty() method to you can determine whether any clauses actually exist. This helps when building the Queries upstream b/c we won't include, or will alter our Query if a particular BooleanJunction is empty since it will not provide the results desired.

What is the equivalent for BooleanPredicateClausesStep in Hibernate Search 6? I don't see one, so is there another way to determine whether a BooleanPredicateClausesStep is empty or has no clauses contained within it?

Providing some example code to illustrate.

Hibernate Search 5.10.7.Final:

     public Query buildProbableVendorNamesQuery(FullTextSession fts, QueryBuilder qb, Set<String> vendorNames) {
            BooleanJunction namesBool = qb.bool();

            vendorNames.forEach(name ->
                    addProbableVendorNameBool(fts, qb, namesBool, name)
            );
    
            return namesBool.isEmpty() ? null : namesBool.createQuery();
        }

Hibernate Search 6.1.5.Final:

    public SearchPredicate buildProbableVendorNamesPredicate(SearchPredicateFactory pf, Set<String> vendorNames) {
        BooleanPredicateClausesStep namesBool = pf.bool();

        vendorNames.forEach(name ->
                addProbableVendorNameBool(pf, namesBool, name)
        );

        //TODO: How can we know if namesBool is empty so we can return null?
        return namesBool.toPredicate();
    }

There are various reasons why namesBool could be empty, 1 being that the name itself ended up being a stop word or normalizing down to nothing. In that case we'd want to inform the caller upstream that the SearchPredicate is null so don't attempt to use it in a query.

CodePudding user response:

There is no equivalent in Hibernate Search 6 at the moment. I created HSEARCH-4618 to address that; if you want the feature soon, you can consider contributing, as this would be a relatively easy first contribution to Hibernate Search.

In the meantime, you can pass a List to addProbableVendorNameBool as a workaround. While not very pretty, it will work:

    public SearchPredicate buildProbableVendorNamesPredicate(SearchPredicateFactory pf, Set<String> vendorNames) {
        List<SearchPredicate> clauses = new ArrayList();

        vendorNames.forEach(name ->
                addProbableVendorNameBool(pf, clauses, name)
        );

        if (clauses.isEmpty()) {
            return null;
        }

        BooleanPredicateClausesStep namesBool = pf.bool();
        clauses.forEach(namesBool::should);
        return namesBool.toPredicate();
    }

    private void addProbableVendorNameBool(SearchPredicateFactory pf, List<SearchPredicate> clauses, String name) {
        ...
    }

Or, if you can change addProbableVendorNameBool so that it returns exactly exactly one predicate (e.g. by having it create its own boolean predicate if necessary) or null:

    public SearchPredicate buildProbableVendorNamesPredicate(SearchPredicateFactory pf, Set<String> vendorNames) {
        List<SearchPredicate> clauses = vendorNames.stream()
                .map(name -> buildProbableVendorSingleNamePredicate(pf, name))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (clauses.isEmpty()) {
            return null;
        }

        BooleanPredicateClausesStep namesBool = pf.bool();
        clauses.forEach(namesBool::should);
        return namesBool.toPredicate();
    }

    private SearchPredicate buildProbableVendorSingleNamePredicate(SearchPredicateFactory pf, String name) {
        ...
        return <something or null>;
    }
  • Related