Skip to content

Commit

Permalink
HSEARCH-3752 Support recursive implicit nested predicates in Lucene
Browse files Browse the repository at this point in the history
  • Loading branch information
fax4ever committed Mar 18, 2020
1 parent 78b97d5 commit f01e42a
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 23 deletions.
Expand Up @@ -6,23 +6,59 @@
*/
package org.hibernate.search.backend.lucene.search.predicate.impl;

import java.util.LinkedList;
import java.util.List;

import org.hibernate.search.util.common.AssertionFailure;

import org.apache.lucene.search.Query;

public abstract class AbstractLuceneSearchNestedPredicateBuilder extends AbstractLuceneSearchPredicateBuilder {

private final String nestedDocumentPath;
private final List<String> nestedPathHierarchy;

public AbstractLuceneSearchNestedPredicateBuilder(String nestedDocumentPath) {
this.nestedDocumentPath = nestedDocumentPath;
public AbstractLuceneSearchNestedPredicateBuilder(List<String> nestedPathHierarchy) {
this.nestedPathHierarchy = nestedPathHierarchy;
}

@Override
public final Query build(LuceneSearchPredicateContext context) {
if ( nestedDocumentPath == null || nestedDocumentPath.equals( context.getNestedPath() ) ) {
List<String> nestedSteps = implicitNestedSteps( context );
return applyImplicitNestedSteps( nestedSteps, context );
}

private List<String> implicitNestedSteps(LuceneSearchPredicateContext context) {
String contextNestedPath = context.getNestedPath();

if ( contextNestedPath == null ) {
// we need to handle all the nestedPathHierarchy belong to the target
return new LinkedList<>( nestedPathHierarchy );
}

int contextNestedPathIndex = nestedPathHierarchy.indexOf( contextNestedPath );
if ( contextNestedPathIndex < 0 ) {
throw new AssertionFailure( "The nested path must belong to the nested path hierarchy: there's an Hibernate Search bug." );
}

// we need to handle just the last part of the nestedPathHierarchy belong to the target,
// the one that hasn't been handled by the context
return new LinkedList<>( nestedPathHierarchy.subList( contextNestedPathIndex + 1, nestedPathHierarchy.size() ) );
}

private Query applyImplicitNestedSteps(List<String> furtherImplicitNestedSteps, LuceneSearchPredicateContext context) {
if ( furtherImplicitNestedSteps.isEmpty() ) {
return super.build( context );
}

LuceneSearchPredicateContext childContext = new LuceneSearchPredicateContext( nestedDocumentPath );
return LuceneNestedPredicateBuilder.doBuild( context, nestedDocumentPath, super.build( childContext ) );
if ( furtherImplicitNestedSteps.size() == 1 ) {
String lastStep = furtherImplicitNestedSteps.get( 0 );
LuceneSearchPredicateContext childContext = new LuceneSearchPredicateContext( lastStep );
// super.build( childContext ) must be called only from the very last nest step
return LuceneNestedPredicateBuilder.doBuild( context, lastStep, super.build( childContext ) );
}

String step = furtherImplicitNestedSteps.remove( 0 );
LuceneSearchPredicateContext childContext = new LuceneSearchPredicateContext( step );
return LuceneNestedPredicateBuilder.doBuild( context, step, applyImplicitNestedSteps( furtherImplicitNestedSteps, childContext ) );
}
}
Expand Up @@ -7,6 +7,7 @@
package org.hibernate.search.backend.lucene.search.predicate.impl;

import java.lang.invoke.MethodHandles;
import java.util.List;

import org.hibernate.search.backend.lucene.logging.impl.Log;
import org.hibernate.search.backend.lucene.scope.model.impl.LuceneCompatibilityChecker;
Expand Down Expand Up @@ -42,10 +43,10 @@ public abstract class AbstractLuceneStandardMatchPredicateBuilder<F, E, C extend

protected AbstractLuceneStandardMatchPredicateBuilder(
LuceneSearchContext searchContext,
String absoluteFieldPath, String nestedDocumentPath,
String absoluteFieldPath, List<String> nestedPathHierarchy,
DslConverter<?, ? extends F> converter, DslConverter<F, ? extends F> rawConverter,
LuceneCompatibilityChecker converterChecker, C codec) {
super( nestedDocumentPath );
super( nestedPathHierarchy );
this.searchContext = searchContext;
this.absoluteFieldPath = absoluteFieldPath;
this.converter = converter;
Expand Down
Expand Up @@ -99,7 +99,7 @@ public BooleanPredicateBuilder<LuceneSearchPredicateBuilder> bool() {
public MatchPredicateBuilder<LuceneSearchPredicateBuilder> match(String absoluteFieldPath) {
LuceneScopedIndexFieldComponent<LuceneFieldPredicateBuilderFactory> fieldComponent = scopeModel.getSchemaNodeComponent(
absoluteFieldPath, PREDICATE_BUILDER_FACTORY_RETRIEVAL_STRATEGY );
return fieldComponent.getComponent().createMatchPredicateBuilder( searchContext, absoluteFieldPath, scopeModel.getNestedDocumentPath( absoluteFieldPath ),
return fieldComponent.getComponent().createMatchPredicateBuilder( searchContext, absoluteFieldPath, scopeModel.getNestedPathHierarchyForField( absoluteFieldPath ),
fieldComponent.getConverterCompatibilityChecker(), fieldComponent.getAnalyzerCompatibilityChecker() );
}

Expand Down
Expand Up @@ -6,6 +6,8 @@
*/
package org.hibernate.search.backend.lucene.types.predicate.impl;

import java.util.List;

import org.hibernate.search.backend.lucene.scope.model.impl.LuceneCompatibilityChecker;
import org.hibernate.search.backend.lucene.search.impl.LuceneSearchContext;
import org.hibernate.search.backend.lucene.search.predicate.impl.LuceneSearchPredicateBuilder;
Expand Down Expand Up @@ -43,7 +45,7 @@ public interface LuceneFieldPredicateBuilderFactory {

boolean hasCompatibleAnalyzer(LuceneFieldPredicateBuilderFactory other);

MatchPredicateBuilder<LuceneSearchPredicateBuilder> createMatchPredicateBuilder( LuceneSearchContext searchContext, String absoluteFieldPath, String nestedDocumentPath,
MatchPredicateBuilder<LuceneSearchPredicateBuilder> createMatchPredicateBuilder( LuceneSearchContext searchContext, String absoluteFieldPath, List<String> nestedPathHierarchy,
LuceneCompatibilityChecker converterChecker, LuceneCompatibilityChecker analyzerChecker);

RangePredicateBuilder<LuceneSearchPredicateBuilder> createRangePredicateBuilder(
Expand Down
Expand Up @@ -7,6 +7,7 @@
package org.hibernate.search.backend.lucene.types.predicate.impl;

import java.lang.invoke.MethodHandles;
import java.util.List;

import org.hibernate.search.backend.lucene.logging.impl.Log;
import org.hibernate.search.backend.lucene.scope.model.impl.LuceneCompatibilityChecker;
Expand Down Expand Up @@ -41,8 +42,8 @@ public LuceneGeoPointFieldPredicateBuilderFactory( boolean searchable,
}

@Override
public MatchPredicateBuilder<LuceneSearchPredicateBuilder> createMatchPredicateBuilder(LuceneSearchContext searchContext, String absoluteFieldPath, String nestedDocumentPath,
LuceneCompatibilityChecker converterChecker, LuceneCompatibilityChecker analyzerChecker) {
public MatchPredicateBuilder<LuceneSearchPredicateBuilder> createMatchPredicateBuilder(LuceneSearchContext searchContext, String absoluteFieldPath,
List<String> nestedPathHierarchy, LuceneCompatibilityChecker converterChecker, LuceneCompatibilityChecker analyzerChecker) {
throw log.directValueLookupNotSupportedByGeoPoint(
EventContexts.fromIndexFieldAbsolutePath( absoluteFieldPath )
);
Expand Down
Expand Up @@ -6,6 +6,8 @@
*/
package org.hibernate.search.backend.lucene.types.predicate.impl;

import java.util.List;

import org.hibernate.search.backend.lucene.scope.model.impl.LuceneCompatibilityChecker;
import org.hibernate.search.backend.lucene.search.impl.LuceneSearchContext;
import org.hibernate.search.backend.lucene.search.predicate.impl.LuceneSearchPredicateBuilder;
Expand All @@ -29,10 +31,10 @@ public LuceneNumericFieldPredicateBuilderFactory( boolean searchable,
}

@Override
public MatchPredicateBuilder<LuceneSearchPredicateBuilder> createMatchPredicateBuilder(LuceneSearchContext searchContext, String absoluteFieldPath, String nestedDocumentPath,
LuceneCompatibilityChecker converterChecker, LuceneCompatibilityChecker analyzerChecker) {
public MatchPredicateBuilder<LuceneSearchPredicateBuilder> createMatchPredicateBuilder(LuceneSearchContext searchContext, String absoluteFieldPath,
List<String> nestedPathHierarchy, LuceneCompatibilityChecker converterChecker, LuceneCompatibilityChecker analyzerChecker) {
checkSearchable( absoluteFieldPath );
return new LuceneNumericMatchPredicateBuilder<>( searchContext, absoluteFieldPath, nestedDocumentPath, converter, rawConverter, converterChecker, codec );
return new LuceneNumericMatchPredicateBuilder<>( searchContext, absoluteFieldPath, nestedPathHierarchy, converter, rawConverter, converterChecker, codec );
}

@Override
Expand Down
Expand Up @@ -6,6 +6,8 @@
*/
package org.hibernate.search.backend.lucene.types.predicate.impl;

import java.util.List;

import org.hibernate.search.backend.lucene.scope.model.impl.LuceneCompatibilityChecker;
import org.hibernate.search.backend.lucene.search.impl.LuceneSearchContext;
import org.hibernate.search.backend.lucene.search.predicate.impl.AbstractLuceneStandardMatchPredicateBuilder;
Expand All @@ -19,11 +21,10 @@ class LuceneNumericMatchPredicateBuilder<F, E extends Number>
extends AbstractLuceneStandardMatchPredicateBuilder<F, E, AbstractLuceneNumericFieldCodec<F, E>> {

LuceneNumericMatchPredicateBuilder(
LuceneSearchContext searchContext,
String absoluteFieldPath, String nestedDocumentPath,
LuceneSearchContext searchContext, String absoluteFieldPath, List<String> nestedPathHierarchy,
DslConverter<?, ? extends F> converter, DslConverter<F, ? extends F> rawConverter,
LuceneCompatibilityChecker converterChecker, AbstractLuceneNumericFieldCodec<F, E> codec) {
super( searchContext, absoluteFieldPath, nestedDocumentPath, converter, rawConverter, converterChecker, codec );
super( searchContext, absoluteFieldPath, nestedPathHierarchy, converter, rawConverter, converterChecker, codec );
}

@Override
Expand Down
Expand Up @@ -6,6 +6,7 @@
*/
package org.hibernate.search.backend.lucene.types.predicate.impl;

import java.util.List;
import java.util.Objects;

import org.hibernate.search.backend.lucene.scope.model.impl.LuceneCompatibilityChecker;
Expand All @@ -31,11 +32,11 @@ public LuceneTextFieldPredicateBuilderFactory(boolean searchable,
}

@Override
public LuceneTextMatchPredicateBuilder<?> createMatchPredicateBuilder(LuceneSearchContext searchContext, String absoluteFieldPath, String nestedDocumentPath,
public LuceneTextMatchPredicateBuilder<?> createMatchPredicateBuilder(LuceneSearchContext searchContext, String absoluteFieldPath, List<String> nestedPathHierarchy,
LuceneCompatibilityChecker converterChecker, LuceneCompatibilityChecker analyzerChecker) {
checkSearchable( absoluteFieldPath );
return new LuceneTextMatchPredicateBuilder<>(
searchContext, absoluteFieldPath, nestedDocumentPath, converter, rawConverter, converterChecker, codec, analyzerOrNormalizer, analyzerChecker
searchContext, absoluteFieldPath, nestedPathHierarchy, converter, rawConverter, converterChecker, codec, analyzerOrNormalizer, analyzerChecker
);
}

Expand Down
Expand Up @@ -7,6 +7,7 @@
package org.hibernate.search.backend.lucene.types.predicate.impl;

import java.lang.invoke.MethodHandles;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Term;
Expand Down Expand Up @@ -44,12 +45,11 @@ class LuceneTextMatchPredicateBuilder<F>
private boolean analyzerOverridden = false;

LuceneTextMatchPredicateBuilder(
LuceneSearchContext searchContext,
String absoluteFieldPath, String nestedDocumentPath,
LuceneSearchContext searchContext, String absoluteFieldPath, List<String> nestedPathHierarchy,
DslConverter<?, ? extends F> converter, DslConverter<F, ? extends F> rawConverter,
LuceneCompatibilityChecker converterChecker, LuceneTextFieldCodec<F> codec,
Analyzer analyzerOrNormalizer, LuceneCompatibilityChecker analyzerChecker) {
super( searchContext, absoluteFieldPath, nestedDocumentPath, converter, rawConverter, converterChecker, codec );
super( searchContext, absoluteFieldPath, nestedPathHierarchy, converter, rawConverter, converterChecker, codec );
this.analyzerOrNormalizer = analyzerOrNormalizer;
this.analyzerChecker = analyzerChecker;
this.analysisDefinitionRegistry = searchContext.getAnalysisDefinitionRegistry();
Expand Down

0 comments on commit f01e42a

Please sign in to comment.