Skip to content

Commit

Permalink
HSEARCH-3312 Avoid to touch original query builder instance at query …
Browse files Browse the repository at this point in the history
…time

As a side effect we allow to override analyzer on a not analyzed field
  • Loading branch information
fax4ever authored and yrodiere committed Apr 3, 2019
1 parent 3eb8ad4 commit 620ef3e
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 37 deletions.
Expand Up @@ -34,13 +34,11 @@ class LuceneTextMatchPredicateBuilder<F>

private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private final QueryBuilder queryBuilder;
private final LuceneAnalysisDefinitionRegistry analysisDefinitionRegistry;

private Integer maxEditDistance;
private Integer prefixLength;
private Analyzer overrideAnalyzer;
private boolean ignoreAnalyzer = false;
private Analyzer analyzer;

LuceneTextMatchPredicateBuilder(
LuceneSearchContext searchContext,
Expand All @@ -49,7 +47,7 @@ class LuceneTextMatchPredicateBuilder<F>
LuceneConverterCompatibilityChecker converterChecker, LuceneTextFieldCodec<F> codec,
QueryBuilder queryBuilder) {
super( searchContext, absoluteFieldPath, converter, rawConverter, converterChecker, codec );
this.queryBuilder = queryBuilder;
this.analyzer = ( queryBuilder == null ) ? null : queryBuilder.getAnalyzer();
this.analysisDefinitionRegistry = searchContext.getAnalysisDefinitionRegistry();
}

Expand All @@ -61,27 +59,26 @@ public void fuzzy(int maxEditDistance, int exactPrefixLength) {

@Override
public void analyzer(String analyzerName) {
this.overrideAnalyzer = analysisDefinitionRegistry.getAnalyzerDefinition( analyzerName );
if ( overrideAnalyzer == null ) {
this.analyzer = analysisDefinitionRegistry.getAnalyzerDefinition( analyzerName );
if ( analyzer == null ) {
throw log.unknownAnalyzer( analyzerName, EventContexts.fromIndexFieldAbsolutePath( absoluteFieldPath ) );
}
}

@Override
public void ignoreAnalyzer() {
this.ignoreAnalyzer = true;
this.analyzer = AnalyzerUtils.KEYWORD_ANALYZER;
}

@Override
protected Query doBuild(LuceneSearchPredicateContext context) {
if ( queryBuilder != null ) {
if ( analyzer != null ) {
QueryBuilder effectiveQueryBuilder;
if ( maxEditDistance != null ) {
effectiveQueryBuilder = new FuzzyQueryBuilder( getAnalyzer(), maxEditDistance, prefixLength );
effectiveQueryBuilder = new FuzzyQueryBuilder( analyzer, maxEditDistance, prefixLength );
}
else {
queryBuilder.setAnalyzer( getAnalyzer() );
effectiveQueryBuilder = queryBuilder;
effectiveQueryBuilder = new QueryBuilder( analyzer );
}

Query analyzed = effectiveQueryBuilder.createBooleanQuery( absoluteFieldPath, value );
Expand All @@ -106,14 +103,4 @@ protected Query doBuild(LuceneSearchPredicateContext context) {
}
}
}

private Analyzer getAnalyzer() {
if ( ignoreAnalyzer ) {
return AnalyzerUtils.KEYWORD_ANALYZER;
}
if ( overrideAnalyzer != null ) {
return overrideAnalyzer;
}
return queryBuilder.getAnalyzer();
}
}
Expand Up @@ -35,21 +35,19 @@ class LuceneTextPhrasePredicateBuilder extends AbstractLuceneSearchPredicateBuil
protected final String absoluteFieldPath;
protected final LuceneTextFieldCodec<?> codec;

private final QueryBuilder queryBuilder;
private final LuceneAnalysisDefinitionRegistry analysisDefinitionRegistry;

private int slop;
private String phrase;
private Analyzer overrideAnalyzer;
private boolean ignoreAnalyzer = false;
private Analyzer analyzer;

LuceneTextPhrasePredicateBuilder(
LuceneSearchContext searchContext, String absoluteFieldPath,
LuceneTextFieldCodec<?> codec,
QueryBuilder queryBuilder) {
this.absoluteFieldPath = absoluteFieldPath;
this.codec = codec;
this.queryBuilder = queryBuilder;
this.analyzer = ( queryBuilder == null ) ? null : queryBuilder.getAnalyzer();
this.analysisDefinitionRegistry = searchContext.getAnalysisDefinitionRegistry();
}

Expand All @@ -65,28 +63,21 @@ public void phrase(String phrase) {

@Override
public void analyzer(String analyzerName) {
this.overrideAnalyzer = analysisDefinitionRegistry.getAnalyzerDefinition( analyzerName );
if ( overrideAnalyzer == null ) {
this.analyzer = analysisDefinitionRegistry.getAnalyzerDefinition( analyzerName );
if ( analyzer == null ) {
throw log.unknownAnalyzer( analyzerName, EventContexts.fromIndexFieldAbsolutePath( absoluteFieldPath ) );
}
}

@Override
public void ignoreAnalyzer() {
this.ignoreAnalyzer = true;
this.analyzer = AnalyzerUtils.KEYWORD_ANALYZER;
}

@Override
protected Query doBuild(LuceneSearchPredicateContext context) {
if ( queryBuilder != null ) {
if ( ignoreAnalyzer ) {
queryBuilder.setAnalyzer( AnalyzerUtils.KEYWORD_ANALYZER );
}
else if ( overrideAnalyzer != null ) {
queryBuilder.setAnalyzer( overrideAnalyzer );
}

Query analyzed = queryBuilder.createPhraseQuery( absoluteFieldPath, phrase, slop );
if ( analyzer != null ) {
Query analyzed = new QueryBuilder( analyzer ).createPhraseQuery( absoluteFieldPath, phrase, slop );
if ( analyzed == null ) {
// Either the value was an empty string
// or the analysis removed all tokens (that can happen if the value contained only stopwords, for example)
Expand Down
Expand Up @@ -916,6 +916,22 @@ public void analyzerIgnore_fuzzy() {
.hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_1, DOCUMENT_2, DOCUMENT_3 );
}

@Test
public void analyzerOverride_normalizedStringField() {
StubMappingSearchScope scope = indexManager.createSearchScope();
String absoluteFieldPath = indexMapping.normalizedStringField.relativeFieldName;

IndexSearchQuery<DocumentReference> query = scope.query()
.asReference()
// the matching parameter will be tokenized even if the field has a normalizer
.predicate( f -> f.match().onField( absoluteFieldPath ).matching( "Auster Coe" )
.analyzer( OverrideAnalysisDefinitions.ANALYZER_WHITESPACE_LOWERCASE.name ) )
.toQuery();

assertThat( query )
.hasDocRefHitsAnyOrder( INDEX_NAME, DOCUMENT_2, DOCUMENT_3 );
}

@Test
public void multiFields() {
StubMappingSearchScope scope = indexManager.createSearchScope();
Expand Down

0 comments on commit 620ef3e

Please sign in to comment.