Fix AnalysisMode propagation in NamedAnalyzer (#44626)

NamedAnalyzer should return the same AnalysisMode than any custom analyzer it
wraps, otherwise AnalysisMode.ALL. This used to be only CustomAnalyzer in the
past, but with the introduction of the ReloadableCustomAnalyzer this needs to be
added as an option where the analysis mode gets propagated.

Closes #44625
This commit is contained in:
Christoph Büscher 2019-07-19 18:15:11 +02:00
parent c3b6ab4dec
commit eafe54c81c
3 changed files with 46 additions and 4 deletions

View File

@ -53,8 +53,8 @@ public class NamedAnalyzer extends DelegatingAnalyzerWrapper {
this.scope = scope; this.scope = scope;
this.analyzer = analyzer; this.analyzer = analyzer;
this.positionIncrementGap = positionIncrementGap; this.positionIncrementGap = positionIncrementGap;
if (analyzer instanceof org.elasticsearch.index.analysis.CustomAnalyzer) { if (analyzer instanceof org.elasticsearch.index.analysis.AnalyzerComponentsProvider) {
this.analysisMode = ((org.elasticsearch.index.analysis.CustomAnalyzer) analyzer).getAnalysisMode(); this.analysisMode = ((org.elasticsearch.index.analysis.AnalyzerComponentsProvider) analyzer).getComponents().analysisMode();
} else { } else {
this.analysisMode = AnalysisMode.ALL; this.analysisMode = AnalysisMode.ALL;
} }

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.analysis;
import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.elasticsearch.index.mapper.MapperException; import org.elasticsearch.index.mapper.MapperException;
import org.elasticsearch.index.mapper.TextFieldMapper;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
public class NamedAnalyzerTests extends ESTestCase { public class NamedAnalyzerTests extends ESTestCase {
@ -73,7 +74,13 @@ public class NamedAnalyzerTests extends ESTestCase {
return mode; return mode;
} }
}; };
return new CustomAnalyzer(null, new CharFilterFactory[0], TokenFilterFactory[] tokenfilters = new TokenFilterFactory[] { tokenFilter };
new TokenFilterFactory[] { tokenFilter }); CharFilterFactory[] charFilters = new CharFilterFactory[0];
if (mode == AnalysisMode.SEARCH_TIME && randomBoolean()) {
AnalyzerComponents components = new AnalyzerComponents(null, charFilters, tokenfilters);
// sometimes also return reloadable custom analyzer
return new ReloadableCustomAnalyzer(components , TextFieldMapper.Defaults.POSITION_INCREMENT_GAP, -1);
}
return new CustomAnalyzer(null, charFilters, tokenfilters);
} }
} }

View File

@ -11,6 +11,7 @@ import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction.Response;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.analysis.common.CommonAnalysisPlugin; import org.elasticsearch.analysis.common.CommonAnalysisPlugin;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.mapper.MapperException;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.ESSingleNodeTestCase;
@ -104,4 +105,38 @@ public class ReloadSynonymAnalyzerTests extends ESSingleNodeTestCase {
response = client().prepareSearch(indexName).setQuery(QueryBuilders.matchQuery("field", "buzz")).get(); response = client().prepareSearch(indexName).setQuery(QueryBuilders.matchQuery("field", "buzz")).get();
assertHitCount(response, 1L); assertHitCount(response, 1L);
} }
public void testUpdateableSynonymsRejectedAtIndexTime() throws FileNotFoundException, IOException {
String synonymsFileName = "synonyms.txt";
Path configDir = node().getEnvironment().configFile();
if (Files.exists(configDir) == false) {
Files.createDirectory(configDir);
}
Path synonymsFile = configDir.resolve(synonymsFileName);
if (Files.exists(synonymsFile) == false) {
Files.createFile(synonymsFile);
}
try (PrintWriter out = new PrintWriter(
new OutputStreamWriter(Files.newOutputStream(synonymsFile, StandardOpenOption.WRITE), StandardCharsets.UTF_8))) {
out.println("foo, baz");
}
final String indexName = "test";
final String analyzerName = "my_synonym_analyzer";
MapperException ex = expectThrows(MapperException.class, () -> client().admin().indices().prepareCreate(indexName)
.setSettings(Settings.builder()
.put("index.number_of_shards", 5)
.put("index.number_of_replicas", 0)
.put("analysis.analyzer." + analyzerName + ".tokenizer", "standard")
.putList("analysis.analyzer." + analyzerName + ".filter", "lowercase", "my_synonym_filter")
.put("analysis.filter.my_synonym_filter.type", "synonym")
.put("analysis.filter.my_synonym_filter.updateable", "true")
.put("analysis.filter.my_synonym_filter.synonyms_path", synonymsFileName))
.addMapping("_doc", "field", "type=text,analyzer=" + analyzerName).get());
assertEquals(
"Failed to parse mapping [_doc]: analyzer [my_synonym_analyzer] "
+ "contains filters [my_synonym_filter] that are not allowed to run in all mode.",
ex.getMessage());
}
} }