Skip to content

Commit

Permalink
Restore use of default search and search_quote analyzers (#65491)
Browse files Browse the repository at this point in the history
In the refactoring of TextFieldMapper, we lost the ability to define
a default search or search_quote analyzer in index settings. This
commit restores that ability, and adds some more comprehensive
testing.

Fixes #65434
  • Loading branch information
romseygeek committed Nov 26, 2020
1 parent 04f453c commit 1a8ce87
Show file tree
Hide file tree
Showing 20 changed files with 285 additions and 91 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
"Test default search analyzer is applied":
- do:
indices.create:
index: test
body:
settings:
index.analysis.analyzer.default.type: simple
index.analysis.analyzer.default_search.type: german
mappings:
properties:
body:
type: text

- do:
index:
index: test
id: 1
body:
body: Ich lese die Bücher

- do:
indices.refresh:
index: [ test ]

- do:
search:
index: test
q: "body:Bücher"

- match: { hits.total.value: 0 }

- do:
search:
index: test
q: "body:Bücher"
analyzer: simple

- match: { hits.total.value: 1 }
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.apache.lucene.util.automaton.Operations;
import org.elasticsearch.common.collect.Iterators;
import org.elasticsearch.index.analysis.AnalyzerScope;
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.similarity.SimilarityProvider;
Expand All @@ -61,7 +62,6 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

import static org.elasticsearch.index.mapper.TextFieldMapper.TextFieldType.hasGaps;

Expand Down Expand Up @@ -93,7 +93,7 @@ public static class Defaults {
}

public static final TypeParser PARSER
= new TypeParser((n, c) -> new Builder(n, () -> c.getIndexAnalyzers().getDefaultIndexAnalyzer()));
= new TypeParser((n, c) -> new Builder(n, c.getIndexAnalyzers()));

private static Builder builder(FieldMapper in) {
return ((SearchAsYouTypeFieldMapper)in).builder;
Expand Down Expand Up @@ -134,9 +134,9 @@ public static class Builder extends FieldMapper.Builder {

private final Parameter<Map<String, String>> meta = Parameter.metaParam();

public Builder(String name, Supplier<NamedAnalyzer> defaultAnalyzer) {
public Builder(String name, IndexAnalyzers indexAnalyzers) {
super(name);
this.analyzers = new TextParams.Analyzers(defaultAnalyzer, m -> builder(m).analyzers);
this.analyzers = new TextParams.Analyzers(indexAnalyzers, m -> builder(m).analyzers);
}

@Override
Expand Down Expand Up @@ -592,7 +592,7 @@ protected String contentType() {
}

public FieldMapper.Builder getMergeBuilder() {
return new Builder(simpleName(), builder.analyzers.indexAnalyzer::getDefaultValue).init(this);
return new Builder(simpleName(), builder.analyzers.indexAnalyzers).init(this);
}

public static String getShingleFieldName(String parentField, int shingleSize) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.apache.lucene.index.IndexOptions;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.index.analysis.AnalyzerScope;
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.mapper.ContentPath;
import org.elasticsearch.index.mapper.FieldMapper;
Expand All @@ -54,7 +55,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -96,9 +96,9 @@ public static class Builder extends FieldMapper.Builder {

private final Parameter<Map<String, String>> meta = Parameter.metaParam();

public Builder(String name, Supplier<NamedAnalyzer> defaultAnalyzer) {
public Builder(String name, IndexAnalyzers indexAnalyzers) {
super(name);
this.analyzers = new TextParams.Analyzers(defaultAnalyzer, m -> builder(m).analyzers);
this.analyzers = new TextParams.Analyzers(indexAnalyzers, m -> builder(m).analyzers);
}

@Override
Expand All @@ -115,12 +115,11 @@ private AnnotatedTextFieldType buildFieldType(FieldType fieldType, ContentPath c
similarity.get(),
wrapAnalyzer(analyzers.getSearchAnalyzer()),
wrapAnalyzer(analyzers.getSearchQuoteAnalyzer()));
AnnotatedTextFieldType ft = new AnnotatedTextFieldType(
return new AnnotatedTextFieldType(
buildFullName(contentPath),
store.getValue(),
tsi,
meta.getValue());
return ft;
}

@Override
Expand All @@ -141,7 +140,7 @@ name, fieldType, buildFieldType(fieldType, contentPath),
}
}

public static TypeParser PARSER = new TypeParser((n, c) -> new Builder(n, () -> c.getIndexAnalyzers().getDefaultIndexAnalyzer()));
public static TypeParser PARSER = new TypeParser((n, c) -> new Builder(n, c.getIndexAnalyzers()));

/**
* Parses markdown-like syntax into plain text and AnnotationTokens with offsets for
Expand Down Expand Up @@ -546,6 +545,6 @@ protected String contentType() {

@Override
public FieldMapper.Builder getMergeBuilder() {
return new Builder(simpleName(), builder.analyzers.indexAnalyzer::getDefaultValue).init(this);
return new Builder(simpleName(), builder.analyzers.indexAnalyzers).init(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queries.intervals.Intervals;
import org.apache.lucene.queries.intervals.IntervalsSource;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.index.analysis.AnalyzerScope;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.mapper.ContentPath;
Expand All @@ -43,7 +42,7 @@ public void testIntervals() throws IOException {
}

public void testFetchSourceValue() throws IOException {
MappedFieldType fieldType = new AnnotatedTextFieldMapper.Builder("field", () -> Lucene.STANDARD_ANALYZER)
MappedFieldType fieldType = new AnnotatedTextFieldMapper.Builder("field", createDefaultIndexAnalyzers())
.build(new ContentPath())
.fieldType();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -693,8 +693,7 @@ private static Mapper.Builder createBuilderFromDynamicValue(final ParseContext c

Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, XContentFieldType.STRING);
if (builder == null) {
builder = new TextFieldMapper.Builder(currentFieldName,
() -> context.indexAnalyzers().getDefaultIndexAnalyzer())
builder = new TextFieldMapper.Builder(currentFieldName, context.indexAnalyzers())
.addMultiField(new KeywordFieldMapper.Builder("keyword").ignoreAbove(256));
}
return builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.index.analysis.AnalyzerScope;
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.plain.PagedBytesIndexFieldData;
Expand Down Expand Up @@ -266,14 +267,14 @@ public static class Builder extends FieldMapper.Builder {

final TextParams.Analyzers analyzers;

public Builder(String name, Supplier<NamedAnalyzer> defaultAnalyzer) {
this(name, Version.CURRENT, defaultAnalyzer);
public Builder(String name, IndexAnalyzers indexAnalyzers) {
this(name, Version.CURRENT, indexAnalyzers);
}

public Builder(String name, Version indexCreatedVersion, Supplier<NamedAnalyzer> defaultAnalyzer) {
public Builder(String name, Version indexCreatedVersion, IndexAnalyzers indexAnalyzers) {
super(name);
this.indexCreatedVersion = indexCreatedVersion;
this.analyzers = new TextParams.Analyzers(defaultAnalyzer, m -> builder(m).analyzers);
this.analyzers = new TextParams.Analyzers(indexAnalyzers, m -> builder(m).analyzers);
}

public Builder index(boolean index) {
Expand Down Expand Up @@ -421,7 +422,7 @@ public TextFieldMapper build(ContentPath contentPath) {
}

public static final TypeParser PARSER
= new TypeParser((n, c) -> new Builder(n, c.indexVersionCreated(), () -> c.getIndexAnalyzers().getDefaultIndexAnalyzer()));
= new TypeParser((n, c) -> new Builder(n, c.indexVersionCreated(), c.getIndexAnalyzers()));

private static class PhraseWrappedAnalyzer extends AnalyzerWrapper {

Expand Down Expand Up @@ -807,7 +808,7 @@ protected TextFieldMapper(String simpleName, FieldType fieldType,

@Override
public FieldMapper.Builder getMergeBuilder() {
return new Builder(simpleName(), builder.indexCreatedVersion, builder.analyzers.indexAnalyzer::getDefaultValue).init(this);
return new Builder(simpleName(), builder.indexCreatedVersion, builder.analyzers.indexAnalyzers).init(this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexOptions;
import org.elasticsearch.index.analysis.AnalysisMode;
import org.elasticsearch.index.analysis.AnalysisRegistry;
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.mapper.FieldMapper.Parameter;
import org.elasticsearch.index.similarity.SimilarityProvider;
Expand All @@ -44,22 +46,35 @@ public static final class Analyzers {
public final Parameter<NamedAnalyzer> searchAnalyzer;
public final Parameter<NamedAnalyzer> searchQuoteAnalyzer;
public final Parameter<Integer> positionIncrementGap;
public final IndexAnalyzers indexAnalyzers;

public Analyzers(Supplier<NamedAnalyzer> defaultAnalyzer,
public Analyzers(IndexAnalyzers indexAnalyzers,
Function<FieldMapper, Analyzers> analyzerInitFunction) {
this.indexAnalyzer = Parameter.analyzerParam("analyzer", false,
m -> analyzerInitFunction.apply(m).indexAnalyzer.get(), defaultAnalyzer)
m -> analyzerInitFunction.apply(m).indexAnalyzer.get(), indexAnalyzers::getDefaultIndexAnalyzer)
.setSerializerCheck((id, ic, a) -> id || ic ||
Objects.equals(a, getSearchAnalyzer()) == false || Objects.equals(a, getSearchQuoteAnalyzer()) == false)
.setValidator(a -> a.checkAllowedInMode(AnalysisMode.INDEX_TIME));
this.searchAnalyzer
= Parameter.analyzerParam("search_analyzer", true,
m -> m.fieldType().getTextSearchInfo().getSearchAnalyzer(), indexAnalyzer::getValue)
m -> m.fieldType().getTextSearchInfo().getSearchAnalyzer(), () -> {
NamedAnalyzer defaultAnalyzer = indexAnalyzers.get(AnalysisRegistry.DEFAULT_SEARCH_ANALYZER_NAME);
if (defaultAnalyzer != null) {
return defaultAnalyzer;
}
return indexAnalyzer.get();
})
.setSerializerCheck((id, ic, a) -> id || ic || Objects.equals(a, getSearchQuoteAnalyzer()) == false)
.setValidator(a -> a.checkAllowedInMode(AnalysisMode.SEARCH_TIME));
this.searchQuoteAnalyzer
= Parameter.analyzerParam("search_quote_analyzer", true,
m -> m.fieldType().getTextSearchInfo().getSearchQuoteAnalyzer(), searchAnalyzer::getValue)
m -> m.fieldType().getTextSearchInfo().getSearchQuoteAnalyzer(), () -> {
NamedAnalyzer defaultAnalyzer = indexAnalyzers.get(AnalysisRegistry.DEFAULT_SEARCH_QUOTED_ANALYZER_NAME);
if (defaultAnalyzer != null) {
return defaultAnalyzer;
}
return searchAnalyzer.get();
})
.setValidator(a -> a.checkAllowedInMode(AnalysisMode.SEARCH_TIME));
this.positionIncrementGap = Parameter.intParam("position_increment_gap", false,
m -> analyzerInitFunction.apply(m).positionIncrementGap.get(), POSITION_INCREMENT_GAP_USE_ANALYZER)
Expand All @@ -68,6 +83,7 @@ public Analyzers(Supplier<NamedAnalyzer> defaultAnalyzer,
throw new MapperParsingException("[position_increment_gap] must be positive, got [" + v + "]");
}
});
this.indexAnalyzers = indexAnalyzers;
}

public NamedAnalyzer getIndexAnalyzer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ MappedFieldType failIfFieldMappingNotFound(String name, MappedFieldType fieldMap
return fieldMapping;
} else if (mapUnmappedFieldAsString) {
TextFieldMapper.Builder builder
= new TextFieldMapper.Builder(name, () -> mapperService.getIndexAnalyzers().getDefaultIndexAnalyzer());
= new TextFieldMapper.Builder(name, mapperService.getIndexAnalyzers());
return builder.build(new ContentPath(1)).fieldType();
} else {
throw new QueryShardException(this, "No field mapping can be found for the field with name [{}]", name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.ByteBuffersDirectory;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService;
Expand Down Expand Up @@ -100,7 +99,7 @@ public <IFD extends IndexFieldData<?>> IFD getForField(String type, String field
if (docValues) {
fieldType = new KeywordFieldMapper.Builder(fieldName).build(contentPath).fieldType();
} else {
fieldType = new TextFieldMapper.Builder(fieldName, () -> Lucene.STANDARD_ANALYZER)
fieldType = new TextFieldMapper.Builder(fieldName, createDefaultIndexAnalyzers())
.fielddata(true).build(contentPath).fieldType();
}
} else if (type.equals("float")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.SortedSetDocValues;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.index.mapper.ContentPath;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.TextFieldMapper;
Expand Down Expand Up @@ -64,7 +63,7 @@ public void testFilterByFrequency() throws Exception {

{
indexService.clearCaches(false, true);
MappedFieldType ft = new TextFieldMapper.Builder("high_freq", () -> Lucene.STANDARD_ANALYZER)
MappedFieldType ft = new TextFieldMapper.Builder("high_freq", createDefaultIndexAnalyzers())
.fielddata(true)
.fielddataFrequencyFilter(0, random.nextBoolean() ? 100 : 0.5d, 0)
.build(contentPath).fieldType();
Expand All @@ -79,7 +78,7 @@ public void testFilterByFrequency() throws Exception {
}
{
indexService.clearCaches(false, true);
MappedFieldType ft = new TextFieldMapper.Builder("high_freq", () -> Lucene.STANDARD_ANALYZER)
MappedFieldType ft = new TextFieldMapper.Builder("high_freq", createDefaultIndexAnalyzers())
.fielddata(true)
.fielddataFrequencyFilter(random.nextBoolean() ? 101 : 101d/200.0d, 201, 100)
.build(contentPath).fieldType();
Expand All @@ -94,7 +93,7 @@ public void testFilterByFrequency() throws Exception {

{
indexService.clearCaches(false, true);// test # docs with value
MappedFieldType ft = new TextFieldMapper.Builder("med_freq", () -> Lucene.STANDARD_ANALYZER)
MappedFieldType ft = new TextFieldMapper.Builder("med_freq", createDefaultIndexAnalyzers())
.fielddata(true)
.fielddataFrequencyFilter(random.nextBoolean() ? 101 : 101d/200.0d, Integer.MAX_VALUE, 101)
.build(contentPath).fieldType();
Expand All @@ -110,7 +109,7 @@ public void testFilterByFrequency() throws Exception {

{
indexService.clearCaches(false, true);
MappedFieldType ft = new TextFieldMapper.Builder("med_freq", () -> Lucene.STANDARD_ANALYZER)
MappedFieldType ft = new TextFieldMapper.Builder("med_freq", createDefaultIndexAnalyzers())
.fielddata(true)
.fielddataFrequencyFilter(random.nextBoolean() ? 101 : 101d/200.0d, Integer.MAX_VALUE, 101)
.build(contentPath).fieldType();
Expand All @@ -127,7 +126,7 @@ public void testFilterByFrequency() throws Exception {
}

@Override
public void testEmpty() throws Exception {
public void testEmpty() {
assumeTrue("No need to test empty usage here", false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import org.apache.lucene.store.ByteBuffersDirectory;
import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.SetOnce;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService;
Expand Down Expand Up @@ -142,9 +141,9 @@ public void testClearField() throws Exception {

final ContentPath contentPath = new ContentPath(1);
final MappedFieldType mapper1
= new TextFieldMapper.Builder("field_1", () -> Lucene.STANDARD_ANALYZER).fielddata(true).build(contentPath).fieldType();
= new TextFieldMapper.Builder("field_1", createDefaultIndexAnalyzers()).fielddata(true).build(contentPath).fieldType();
final MappedFieldType mapper2
= new TextFieldMapper.Builder("field_2", () -> Lucene.STANDARD_ANALYZER).fielddata(true).build(contentPath).fieldType();
= new TextFieldMapper.Builder("field_2", createDefaultIndexAnalyzers()).fielddata(true).build(contentPath).fieldType();
final IndexWriter writer = new IndexWriter(new ByteBuffersDirectory(), new IndexWriterConfig(new KeywordAnalyzer()));
Document doc = new Document();
doc.add(new StringField("field_1", "thisisastring", Store.NO));
Expand Down Expand Up @@ -208,7 +207,7 @@ public void testFieldDataCacheListener() throws Exception {

final ContentPath contentPath = new ContentPath(1);
final MappedFieldType mapper1
= new TextFieldMapper.Builder("s", () -> Lucene.STANDARD_ANALYZER).fielddata(true).build(contentPath).fieldType();
= new TextFieldMapper.Builder("s", createDefaultIndexAnalyzers()).fielddata(true).build(contentPath).fieldType();
final IndexWriter writer = new IndexWriter(new ByteBuffersDirectory(), new IndexWriterConfig(new KeywordAnalyzer()));
Document doc = new Document();
doc.add(new StringField("s", "thisisastring", Store.NO));
Expand Down

0 comments on commit 1a8ce87

Please sign in to comment.