From eafe54c81c47e80fbcf870306b878134c4c4cec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Fri, 19 Jul 2019 18:15:11 +0200 Subject: [PATCH] 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 --- .../index/analysis/NamedAnalyzer.java | 4 +-- .../index/analysis/NamedAnalyzerTests.java | 11 ++++-- .../action/ReloadSynonymAnalyzerTests.java | 35 +++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/analysis/NamedAnalyzer.java b/server/src/main/java/org/elasticsearch/index/analysis/NamedAnalyzer.java index 0c53cc323d6..d7e8696421d 100644 --- a/server/src/main/java/org/elasticsearch/index/analysis/NamedAnalyzer.java +++ b/server/src/main/java/org/elasticsearch/index/analysis/NamedAnalyzer.java @@ -53,8 +53,8 @@ public class NamedAnalyzer extends DelegatingAnalyzerWrapper { this.scope = scope; this.analyzer = analyzer; this.positionIncrementGap = positionIncrementGap; - if (analyzer instanceof org.elasticsearch.index.analysis.CustomAnalyzer) { - this.analysisMode = ((org.elasticsearch.index.analysis.CustomAnalyzer) analyzer).getAnalysisMode(); + if (analyzer instanceof org.elasticsearch.index.analysis.AnalyzerComponentsProvider) { + this.analysisMode = ((org.elasticsearch.index.analysis.AnalyzerComponentsProvider) analyzer).getComponents().analysisMode(); } else { this.analysisMode = AnalysisMode.ALL; } diff --git a/server/src/test/java/org/elasticsearch/index/analysis/NamedAnalyzerTests.java b/server/src/test/java/org/elasticsearch/index/analysis/NamedAnalyzerTests.java index 2caaca53cae..b1e53bed96e 100644 --- a/server/src/test/java/org/elasticsearch/index/analysis/NamedAnalyzerTests.java +++ b/server/src/test/java/org/elasticsearch/index/analysis/NamedAnalyzerTests.java @@ -22,6 +22,7 @@ package org.elasticsearch.index.analysis; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.elasticsearch.index.mapper.MapperException; +import org.elasticsearch.index.mapper.TextFieldMapper; import org.elasticsearch.test.ESTestCase; public class NamedAnalyzerTests extends ESTestCase { @@ -73,7 +74,13 @@ public class NamedAnalyzerTests extends ESTestCase { return mode; } }; - return new CustomAnalyzer(null, new CharFilterFactory[0], - new TokenFilterFactory[] { tokenFilter }); + TokenFilterFactory[] tokenfilters = 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); } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/action/ReloadSynonymAnalyzerTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/action/ReloadSynonymAnalyzerTests.java index 590e4bb982e..ef11e485867 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/action/ReloadSynonymAnalyzerTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/action/ReloadSynonymAnalyzerTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction.Response; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.analysis.common.CommonAnalysisPlugin; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.mapper.MapperException; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.ESSingleNodeTestCase; @@ -104,4 +105,38 @@ public class ReloadSynonymAnalyzerTests extends ESSingleNodeTestCase { response = client().prepareSearch(indexName).setQuery(QueryBuilders.matchQuery("field", "buzz")).get(); 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()); + } } \ No newline at end of file