Skip to content

Commit

Permalink
HSEARCH-3307 Simplify cross-index compatibility checks for text match…
Browse files Browse the repository at this point in the history
… predicates on Elasticsearch

We have all the information we need in the field context, no need to add
a "dataType" attribute to the factory.
  • Loading branch information
yrodiere committed Jul 21, 2020
1 parent b9f6a61 commit f1e4ba0
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 31 deletions.
Expand Up @@ -412,8 +412,9 @@ SearchException conflictingIdentifierTypesForSearch(ToDocumentIdentifierValueCon
SearchException unexpectedElasticsearchVersion(ElasticsearchVersion configuredVersion,
ElasticsearchVersion actualVersion);

@Message(id = ID_OFFSET_3 + 60, value = "Elasticsearch backend does not support skip analysis on not analyzed field: '%1$s'.")
SearchException skipAnalysisOnKeywordField(String absoluteFieldPath, @Param EventContext context);
@Message(id = ID_OFFSET_3 + 60, value = "Cannot skip analysis on field '%1$s':"
+ " the Elasticsearch backend will always normalize arguments before attempting matches on normalized fields.")
SearchException skipAnalysisOnNormalizedField(String absoluteFieldPath, @Param EventContext context);

@Message(id = ID_OFFSET_3 + 61,
value = "Ambiguous Elasticsearch version: '%s'."
Expand Down
Expand Up @@ -123,6 +123,16 @@ public Optional<String> normalizerName() {
"normalizer" );
}

@Override
public boolean hasNormalizerOnAtLeastOneIndex() {
for ( ElasticsearchSearchFieldContext<F> fieldContext : fieldForEachIndex ) {
if ( fieldContext.type().hasNormalizerOnAtLeastOneIndex() ) {
return true;
}
}
return false;
}

@Override
public <T> ElasticsearchSearchFieldQueryElementFactory<T, F> queryElementFactory(SearchQueryElementTypeKey<T> key) {
ElasticsearchSearchFieldQueryElementFactory<T, F> factory = null;
Expand Down
Expand Up @@ -52,6 +52,7 @@ default DslConverter<?, F> dslConverter(ValueConvert convert) {

Optional<String> normalizerName();

<T> ElasticsearchSearchFieldQueryElementFactory<T, F> queryElementFactory(SearchQueryElementTypeKey<T> key);
boolean hasNormalizerOnAtLeastOneIndex();

<T> ElasticsearchSearchFieldQueryElementFactory<T, F> queryElementFactory(SearchQueryElementTypeKey<T> key);
}
Expand Up @@ -180,8 +180,7 @@ public IndexFieldType<String> toIndexFieldType() {

if ( resolvedSearchable ) {
builder.searchable( true );
builder.queryElementFactory( PredicateTypeKeys.MATCH,
new ElasticsearchTextMatchPredicate.Factory( codec, mapping.getType() ) );
builder.queryElementFactory( PredicateTypeKeys.MATCH, new ElasticsearchTextMatchPredicate.Factory( codec ) );
builder.queryElementFactory( PredicateTypeKeys.RANGE, new ElasticsearchRangePredicate.Factory<>( codec ) );
builder.queryElementFactory( PredicateTypeKeys.EXISTS, new ElasticsearchExistsPredicate.Factory<>() );
builder.queryElementFactory( PredicateTypeKeys.PHRASE, new ElasticsearchTextPhrasePredicate.Factory() );
Expand Down
Expand Up @@ -142,6 +142,11 @@ public Optional<String> normalizerName() {
return Optional.ofNullable( normalizerName );
}

@Override
public boolean hasNormalizerOnAtLeastOneIndex() {
return normalizerName().isPresent();
}

@Override
public Optional<String> searchAnalyzerName() {
return Optional.ofNullable( searchAnalyzerName );
Expand Down
Expand Up @@ -11,11 +11,9 @@
import org.hibernate.search.backend.elasticsearch.gson.impl.JsonAccessor;
import org.hibernate.search.backend.elasticsearch.logging.impl.Log;
import org.hibernate.search.backend.elasticsearch.lowlevel.index.analysis.impl.AnalyzerConstants;
import org.hibernate.search.backend.elasticsearch.lowlevel.index.mapping.impl.DataTypes;
import org.hibernate.search.backend.elasticsearch.search.impl.AbstractElasticsearchCodecAwareSearchFieldQueryElementFactory;
import org.hibernate.search.backend.elasticsearch.search.impl.ElasticsearchSearchContext;
import org.hibernate.search.backend.elasticsearch.search.impl.ElasticsearchSearchFieldContext;
import org.hibernate.search.backend.elasticsearch.search.impl.ElasticsearchSearchFieldQueryElementFactory;
import org.hibernate.search.backend.elasticsearch.search.predicate.impl.PredicateRequestContext;
import org.hibernate.search.backend.elasticsearch.types.codec.impl.ElasticsearchFieldCodec;
import org.hibernate.search.engine.reporting.spi.EventContexts;
Expand Down Expand Up @@ -61,41 +59,25 @@ protected JsonObject doToJsonQuery(PredicateRequestContext context, JsonObject o

public static class Factory
extends AbstractElasticsearchCodecAwareSearchFieldQueryElementFactory<MatchPredicateBuilder, String> {
private final String dataType;

public Factory(ElasticsearchFieldCodec<String> codec, String dataType) {
public Factory(ElasticsearchFieldCodec<String> codec) {
super( codec );
this.dataType = dataType;
}

@Override
public boolean isCompatibleWith(ElasticsearchSearchFieldQueryElementFactory<?, ?> other) {
if ( !super.isCompatibleWith( other ) ) {
return false;
}

Factory castedOther = (Factory) other;
return dataType.equals( castedOther.dataType );
}

@Override
public MatchPredicateBuilder create(ElasticsearchSearchContext searchContext,
ElasticsearchSearchFieldContext<String> field) {
return new Builder( codec, dataType, searchContext, field );
return new Builder( codec, searchContext, field );
}
}

private static class Builder extends ElasticsearchStandardMatchPredicate.Builder<String> {
private final String type;

private Integer fuzziness;
private Integer prefixLength;
private String analyzer;

private Builder(ElasticsearchFieldCodec<String> codec, String type, ElasticsearchSearchContext searchContext,
private Builder(ElasticsearchFieldCodec<String> codec, ElasticsearchSearchContext searchContext,
ElasticsearchSearchFieldContext<String> field) {
super( codec, searchContext, field );
this.type = type;
}

@Override
Expand All @@ -111,8 +93,8 @@ public void analyzer(String analyzerName) {

@Override
public void skipAnalysis() {
if ( DataTypes.KEYWORD.equals( type ) ) {
throw log.skipAnalysisOnKeywordField( absoluteFieldPath,
if ( field.type().hasNormalizerOnAtLeastOneIndex() ) {
throw log.skipAnalysisOnNormalizedField( absoluteFieldPath,
EventContexts.fromIndexFieldAbsolutePath( absoluteFieldPath ) );
}

Expand Down
Expand Up @@ -41,9 +41,8 @@ public void match_skipAnalysis_normalizedStringField() {
.toQuery()
)
.isInstanceOf( SearchException.class )
.hasMessageContaining( "HSEARCH400560" )
.hasMessageContaining( "Elasticsearch backend does not support skip analysis on not analyzed field" )
.hasMessageContaining( "normalizedStringField" );
.hasMessageContainingAll( "Cannot skip analysis on field 'normalizedStringField'",
"the Elasticsearch backend will always normalize arguments before attempting matches on normalized fields" );
}

private void initData() {
Expand Down

0 comments on commit f1e4ba0

Please sign in to comment.