Skip to content

Commit

Permalink
HSEARCH-4499 New, more fluent API for definition of nested predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
yrodiere committed Mar 30, 2022
1 parent 75a079b commit c0bb8a8
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 107 deletions.
Expand Up @@ -14,6 +14,6 @@
* @param <S> The "self" type (the actual exposed type of this step).
*/
public interface BooleanPredicateClausesStep<S extends BooleanPredicateClausesStep<?>>
extends BooleanPredicateOptionsCollector<S>, PredicateScoreStep<S>, PredicateFinalStep {
extends GenericBooleanPredicateClausesStep<S, BooleanPredicateOptionsCollector<?>> {

}
Expand Up @@ -73,7 +73,7 @@ public interface BooleanPredicateOptionsCollector<S extends BooleanPredicateOpti
* Should generally be a lambda expression.
* @return {@code this}, for method chaining.
*/
S with(Consumer<? super BooleanPredicateOptionsCollector<?>> contributor);
S with(Consumer<? super S> contributor);

/**
* Add a <a href="#must">"must" clause</a> based on a previously-built {@link SearchPredicate}.
Expand Down Expand Up @@ -244,7 +244,7 @@ default S minimumShouldMatchPercent(int matchingClausesPercent) {
*
* @return A {@link MinimumShouldMatchConditionStep} where constraints can be defined.
*/
MinimumShouldMatchConditionStep<S> minimumShouldMatch();
MinimumShouldMatchConditionStep<? extends S> minimumShouldMatch();

/**
* Start defining the minimum number of "should" constraints that have to match
Expand Down
@@ -0,0 +1,98 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.engine.search.predicate.dsl;

import java.util.function.Consumer;
import java.util.function.Function;

import org.hibernate.search.engine.search.predicate.SearchPredicate;

/**
* A generic superinterface for Predicate DSL steps that involve collecting clauses and options of a boolean predicate.
* <p>
* This interface mostly a technical detail to handle generics in the predicate DSL;
* refer to {@link BooleanPredicateOptionsCollector}, {@link PredicateScoreStep} or {@link PredicateFinalStep}
* for meaningful documentation.
*
* @param <S> The "self" type (the actual exposed type of this collector).
* @param <C> The "collector" type (the type of collector passed to the consumer in {@link #with(Consumer)}.
*/
public interface GenericBooleanPredicateClausesStep
<
S extends C,
C extends BooleanPredicateOptionsCollector<?>
>
extends BooleanPredicateOptionsCollector<C>, PredicateScoreStep<S>, PredicateFinalStep {

@Override
S with(Consumer<? super C> contributor);

@Override
S must(SearchPredicate searchPredicate);

@Override
S mustNot(SearchPredicate searchPredicate);

@Override
S should(SearchPredicate searchPredicate);

@Override
S filter(SearchPredicate searchPredicate);

@Override
default S must(PredicateFinalStep dslFinalStep) {
return must( dslFinalStep.toPredicate() );
}

@Override
default S mustNot(PredicateFinalStep dslFinalStep) {
return mustNot( dslFinalStep.toPredicate() );
}

@Override
default S should(PredicateFinalStep dslFinalStep) {
return should( dslFinalStep.toPredicate() );
}

@Override
default S filter(PredicateFinalStep dslFinalStep) {
return filter( dslFinalStep.toPredicate() );
}

@Override
S must(Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor);

@Override
S mustNot(Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor);

@Override
S should(Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor);

@Override
S filter(Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor);

@Override
default S minimumShouldMatchNumber(int matchingClausesNumber) {
return minimumShouldMatch()
.ifMoreThan( 0 ).thenRequireNumber( matchingClausesNumber )
.end();
}

@Override
default S minimumShouldMatchPercent(int matchingClausesPercent) {
return minimumShouldMatch()
.ifMoreThan( 0 ).thenRequirePercent( matchingClausesPercent )
.end();
}

@Override
MinimumShouldMatchConditionStep<S> minimumShouldMatch();

@Override
S minimumShouldMatch(Consumer<? super MinimumShouldMatchConditionStep<?>> constraintContributor);

}
@@ -0,0 +1,23 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.engine.search.predicate.dsl;

/**
* The step in a nested predicate definition where clauses can be added.
* <p>
* Different types of clauses have different effects;
* see {@link BooleanPredicateOptionsCollector}.
*
* @param <S> The "self" type (the actual exposed type of this step).
*/
public interface NestedPredicateClausesStep<S extends NestedPredicateClausesStep<?>>
extends GenericBooleanPredicateClausesStep<S, NestedPredicateOptionsCollector<?>>,
NestedPredicateOptionsCollector<NestedPredicateOptionsCollector<?>> {

// TODO HSEARCH-3090 add tuning methods, like the "score_mode" in Elasticsearch (avg, min, ...)

}
@@ -0,0 +1,17 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.engine.search.predicate.dsl;

/**
* An object where the clauses and options of a {@link SearchPredicateFactory#nested(String)} nested predicate} can be set.
* <p>
* Different types of clauses have different effects, see {@link BooleanPredicateOptionsCollector}.
*/
public interface NestedPredicateOptionsCollector<S extends NestedPredicateOptionsCollector<?>>
extends BooleanPredicateOptionsCollector<S> {

}
Expand Up @@ -147,6 +147,16 @@ public interface SearchPredicateFactory {
*/
NestedPredicateFieldStep<?> nested();

/**
* Match documents where a {@link ObjectStructure#NESTED nested object} matches inner predicates
* to be defined in the next steps.
*
* @param objectFieldPath The <a href="#field-paths">path</a> to the (nested) object field that must match.
* @return The initial step of a DSL where the "nested" predicate can be defined.
* @see NestedPredicateFieldStep
*/
NestedPredicateClausesStep<?> nested(String objectFieldPath);

/**
* Match documents according to a given query string,
* with a simple query language adapted to end users.
Expand Down
@@ -0,0 +1,130 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.engine.search.predicate.dsl.impl;

import java.util.function.Consumer;
import java.util.function.Function;

import org.hibernate.search.engine.search.predicate.SearchPredicate;
import org.hibernate.search.engine.search.predicate.dsl.BooleanPredicateOptionsCollector;
import org.hibernate.search.engine.search.predicate.dsl.GenericBooleanPredicateClausesStep;
import org.hibernate.search.engine.search.predicate.dsl.MinimumShouldMatchConditionStep;
import org.hibernate.search.engine.search.predicate.dsl.PredicateFinalStep;
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactory;
import org.hibernate.search.engine.search.predicate.dsl.spi.AbstractPredicateFinalStep;
import org.hibernate.search.engine.search.predicate.dsl.spi.SearchPredicateDslContext;
import org.hibernate.search.engine.search.predicate.spi.BooleanPredicateBuilder;


abstract class AbstractBooleanPredicateClausesStep<S extends C, C extends BooleanPredicateOptionsCollector<?>>
extends AbstractPredicateFinalStep
implements GenericBooleanPredicateClausesStep<S, C> {

private final SearchPredicateFactory factory;

private final BooleanPredicateBuilder builder;

private final MinimumShouldMatchConditionStepImpl<S> minimumShouldMatchStep;

public AbstractBooleanPredicateClausesStep(SearchPredicateDslContext<?> dslContext,
SearchPredicateFactory factory) {
super( dslContext );
this.factory = factory;
this.builder = dslContext.scope().predicateBuilders().bool();
this.minimumShouldMatchStep = new MinimumShouldMatchConditionStepImpl<>( builder, self() );
}

protected abstract S self();

@Override
public S boost(float boost) {
builder.boost( boost );
return self();
}

@Override
public S constantScore() {
builder.constantScore();
return self();
}

@Override
public S with(Consumer<? super C> contributor) {
contributor.accept( self() );
return self();
}

@Override
public S must(SearchPredicate searchPredicate) {
builder.must( searchPredicate );
return self();
}

@Override
public S mustNot(SearchPredicate searchPredicate) {
builder.mustNot( searchPredicate );
return self();
}

@Override
public S should(SearchPredicate searchPredicate) {
builder.should( searchPredicate );
return self();
}

@Override
public S filter(SearchPredicate searchPredicate) {
builder.filter( searchPredicate );
return self();
}

@Override
public S must(
Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor) {
must( clauseContributor.apply( factory ) );
return self();
}

@Override
public S mustNot(
Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor) {
mustNot( clauseContributor.apply( factory ) );
return self();
}

@Override
public S should(
Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor) {
should( clauseContributor.apply( factory ) );
return self();
}

@Override
public S filter(
Function<? super SearchPredicateFactory, ? extends PredicateFinalStep> clauseContributor) {
filter( clauseContributor.apply( factory ) );
return self();
}

@Override
public MinimumShouldMatchConditionStep<S> minimumShouldMatch() {
return minimumShouldMatchStep;
}

@Override
public S minimumShouldMatch(
Consumer<? super MinimumShouldMatchConditionStep<?>> constraintContributor) {
constraintContributor.accept( minimumShouldMatchStep );
return self();
}

@Override
protected SearchPredicate build() {
return builder.build();
}

}

0 comments on commit c0bb8a8

Please sign in to comment.