Skip to content

Commit 00d5965

Browse files
author
Christoph Büscher
committed
Deprecate and remove camel-case nGram and edgeNGram tokenizers
We already deprecated and removed the camel-case versions of the nGram and edgeNGram filters a while ago and we should do the same with the nGram and edgeNGram tokenizers. This PR deprecates the use of these names in favour of ngram and edge_ngram in 7 and disallows usage in new indices starting with 8. The deprecation part will be backported to 7.6. Closes elastic#50561
1 parent 54f5907 commit 00d5965

File tree

3 files changed

+134
-3
lines changed

3 files changed

+134
-3
lines changed

docs/reference/migration/migrate_8_0/mappings.asciidoc

+9
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,12 @@ The setting has been deprecated with 7.5 and is no longer supported on new indic
3939
Mappings for older indices will continue to work but emit a deprecation warning.
4040
The `enabled` setting for `_field_names` should be removed from templates and mappings.
4141
Disabling _field_names is not necessary because it no longer carries a large index overhead.
42+
43+
[float]
44+
[[nGram-edgeNGram-dreprecation]]
45+
==== Disallow use of the `nGram` and `edgeNGram` tokenizer names
46+
47+
The `nGram` and `edgeNGram` tokenizer names haven been deprecated with 7.6 and are no longer
48+
supported on new indices. Mappings for indices created after 7.6 will continue to work but
49+
emit a deprecation warning. The tokenizer name should be changed to the fully equivalent
50+
`ngram` or `edge_ngram` names for new indices and in index templates.

modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/CommonAnalysisPlugin.java

+41-3
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,29 @@ public Map<String, AnalysisProvider<TokenizerFactory>> getTokenizers() {
337337
tokenizers.put("simple_pattern", SimplePatternTokenizerFactory::new);
338338
tokenizers.put("simple_pattern_split", SimplePatternSplitTokenizerFactory::new);
339339
tokenizers.put("thai", ThaiTokenizerFactory::new);
340-
tokenizers.put("nGram", NGramTokenizerFactory::new);
340+
tokenizers.put("nGram", (IndexSettings indexSettings, Environment environment, String name, Settings settings) -> {
341+
if (indexSettings.getIndexVersionCreated().onOrAfter(org.elasticsearch.Version.V_8_0_0)) {
342+
throw new IllegalArgumentException("The [nGram] tokenizer name was deprecated in 7.6. "
343+
+ "Please use the tokenizer name to [ngram] for indices created in versions 8 or higher instead.");
344+
} else if (indexSettings.getIndexVersionCreated().onOrAfter(org.elasticsearch.Version.V_7_6_0)) {
345+
deprecationLogger.deprecatedAndMaybeLog("nGram_tokenizer_deprecation",
346+
"The [nGram] tokenizer name is deprecated and will be removed in a future version. "
347+
+ "Please change the tokenizer name to [ngram] instead.");
348+
}
349+
return new NGramTokenizerFactory(indexSettings, environment, name, settings);
350+
});
341351
tokenizers.put("ngram", NGramTokenizerFactory::new);
342-
tokenizers.put("edgeNGram", EdgeNGramTokenizerFactory::new);
352+
tokenizers.put("edgeNGram", (IndexSettings indexSettings, Environment environment, String name, Settings settings) -> {
353+
if (indexSettings.getIndexVersionCreated().onOrAfter(org.elasticsearch.Version.V_8_0_0)) {
354+
throw new IllegalArgumentException("The [edgeNGram] tokenizer name was deprecated in 7.6. "
355+
+ "Please use the tokenizer name to [edge_nGram] for indices created in versions 8 or higher instead.");
356+
} else if (indexSettings.getIndexVersionCreated().onOrAfter(org.elasticsearch.Version.V_7_6_0)) {
357+
deprecationLogger.deprecatedAndMaybeLog("edgeNGram_tokenizer_deprecation",
358+
"The [edgeNGram] tokenizer name is deprecated and will be removed in a future version. "
359+
+ "Please change the tokenizer name to [edge_ngram] instead.");
360+
}
361+
return new EdgeNGramTokenizerFactory(indexSettings, environment, name, settings);
362+
});
343363
tokenizers.put("edge_ngram", EdgeNGramTokenizerFactory::new);
344364
tokenizers.put("char_group", CharGroupTokenizerFactory::new);
345365
tokenizers.put("classic", ClassicTokenizerFactory::new);
@@ -522,8 +542,26 @@ public List<PreConfiguredTokenizer> getPreConfiguredTokenizers() {
522542
tokenizers.add(PreConfiguredTokenizer.singleton("lowercase", XLowerCaseTokenizer::new));
523543

524544
// Temporary shim for aliases. TODO deprecate after they are moved
525-
tokenizers.add(PreConfiguredTokenizer.singleton("nGram", NGramTokenizer::new));
545+
tokenizers.add(PreConfiguredTokenizer.elasticsearchVersion("nGram", (version) -> {
546+
if (version.onOrAfter(org.elasticsearch.Version.V_8_0_0)) {
547+
throw new IllegalArgumentException("The [nGram] tokenizer name was deprecated in 7.6. "
548+
+ "Please use the tokenizer name to [ngram] for indices created in versions 8 or higher instead.");
549+
} else if (version.onOrAfter(org.elasticsearch.Version.V_7_6_0)) {
550+
deprecationLogger.deprecatedAndMaybeLog("nGram_tokenizer_deprecation",
551+
"The [nGram] tokenizer name is deprecated and will be removed in a future version. "
552+
+ "Please change the tokenizer name to [ngram] instead.");
553+
}
554+
return new NGramTokenizer();
555+
}));
526556
tokenizers.add(PreConfiguredTokenizer.elasticsearchVersion("edgeNGram", (version) -> {
557+
if (version.onOrAfter(org.elasticsearch.Version.V_8_0_0)) {
558+
throw new IllegalArgumentException("The [edgeNGram] tokenizer name was deprecated in 7.6. "
559+
+ "Please use the tokenizer name to [edge_ngram] for indices created in versions 8 or higher instead.");
560+
} else if (version.onOrAfter(org.elasticsearch.Version.V_7_6_0)) {
561+
deprecationLogger.deprecatedAndMaybeLog("nGram_tokenizer_deprecation",
562+
"The [edgeNGram] tokenizer name is deprecated and will be removed in a future version. "
563+
+ "Please change the tokenizer name to [edge_ngram] instead.");
564+
}
527565
if (version.onOrAfter(Version.V_7_3_0)) {
528566
return new EdgeNGramTokenizer(NGramTokenizer.DEFAULT_MIN_NGRAM_SIZE, NGramTokenizer.DEFAULT_MAX_NGRAM_SIZE);
529567
}

modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/CommonAnalysisPluginTests.java

+84
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.elasticsearch.common.settings.Settings;
2727
import org.elasticsearch.env.Environment;
2828
import org.elasticsearch.index.analysis.TokenFilterFactory;
29+
import org.elasticsearch.index.analysis.TokenizerFactory;
2930
import org.elasticsearch.test.ESTestCase;
3031
import org.elasticsearch.test.IndexSettingsModule;
3132
import org.elasticsearch.test.VersionUtils;
@@ -126,4 +127,87 @@ public void testEdgeNGramFilterInCustomAnalyzerDeprecationError() throws IOExcep
126127
+ "Please change the filter name to [edge_ngram] instead.");
127128
}
128129
}
130+
131+
/**
132+
* Check that we log a deprecation warning for "nGram" and "edgeNGram" tokenizer names with 7.6 and
133+
* disallow usages for indices created after 8.0
134+
*/
135+
public void testNGramTokenizerDeprecation() throws IOException {
136+
// tests for prebuilt tokenizer
137+
doTestPrebuiltTokenizerDeprecation("nGram", "ngram",
138+
VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_5_2), false);
139+
doTestPrebuiltTokenizerDeprecation("edgeNGram", "edge_ngram",
140+
VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_5_2), false);
141+
doTestPrebuiltTokenizerDeprecation("nGram", "ngram",
142+
VersionUtils.randomVersionBetween(random(), Version.V_7_6_0,
143+
Version.max(Version.V_7_6_0, VersionUtils.getPreviousVersion(Version.V_8_0_0))),
144+
true);
145+
doTestPrebuiltTokenizerDeprecation("edgeNGram", "edge_ngram",
146+
VersionUtils.randomVersionBetween(random(), Version.V_7_6_0,
147+
Version.max(Version.V_7_6_0, VersionUtils.getPreviousVersion(Version.V_8_0_0))), true);
148+
expectThrows(IllegalArgumentException.class, () -> doTestPrebuiltTokenizerDeprecation("nGram", "ngram",
149+
VersionUtils.randomVersionBetween(random(), Version.V_8_0_0, Version.CURRENT), true));
150+
expectThrows(IllegalArgumentException.class, () -> doTestPrebuiltTokenizerDeprecation("edgeNGram", "edge_ngram",
151+
VersionUtils.randomVersionBetween(random(), Version.V_8_0_0, Version.CURRENT), true));
152+
153+
// same batch of tests for custom tokenizer definition in the settings
154+
doTestCustomTokenizerDeprecation("nGram", "ngram",
155+
VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_5_2), false);
156+
doTestCustomTokenizerDeprecation("edgeNGram", "edge_ngram",
157+
VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.V_7_5_2), false);
158+
doTestCustomTokenizerDeprecation("nGram", "ngram",
159+
VersionUtils.randomVersionBetween(random(), Version.V_7_6_0,
160+
Version.max(Version.V_7_6_0, VersionUtils.getPreviousVersion(Version.V_8_0_0))),
161+
true);
162+
doTestCustomTokenizerDeprecation("edgeNGram", "edge_ngram",
163+
VersionUtils.randomVersionBetween(random(), Version.V_7_6_0,
164+
Version.max(Version.V_7_6_0, VersionUtils.getPreviousVersion(Version.V_8_0_0))), true);
165+
expectThrows(IllegalArgumentException.class, () -> doTestCustomTokenizerDeprecation("nGram", "ngram",
166+
VersionUtils.randomVersionBetween(random(), Version.V_8_0_0, Version.CURRENT), true));
167+
expectThrows(IllegalArgumentException.class, () -> doTestCustomTokenizerDeprecation("edgeNGram", "edge_ngram",
168+
VersionUtils.randomVersionBetween(random(), Version.V_8_0_0, Version.CURRENT), true));
169+
170+
}
171+
172+
public void doTestPrebuiltTokenizerDeprecation(String deprecatedName, String replacement, Version version, boolean expectWarning)
173+
throws IOException {
174+
final Settings settings = Settings.builder().put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
175+
.put(IndexMetaData.SETTING_VERSION_CREATED, version).build();
176+
177+
try (CommonAnalysisPlugin commonAnalysisPlugin = new CommonAnalysisPlugin()) {
178+
Map<String, TokenizerFactory> tokenizers = createTestAnalysis(
179+
IndexSettingsModule.newIndexSettings("index", settings), settings, commonAnalysisPlugin).tokenizer;
180+
TokenizerFactory tokenizerFactory = tokenizers.get(deprecatedName);
181+
182+
Tokenizer tokenizer = tokenizerFactory.create();
183+
assertNotNull(tokenizer);
184+
if (expectWarning) {
185+
assertWarnings("The [" + deprecatedName + "] tokenizer name is deprecated and will be removed in a future version. "
186+
+ "Please change the tokenizer name to [" + replacement + "] instead.");
187+
}
188+
}
189+
}
190+
191+
public void doTestCustomTokenizerDeprecation(String deprecatedName, String replacement, Version version, boolean expectWarning)
192+
throws IOException {
193+
final Settings settings = Settings.builder().put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
194+
.put(IndexMetaData.SETTING_VERSION_CREATED, version)
195+
.put("index.analysis.analyzer.custom_analyzer.type", "custom")
196+
.put("index.analysis.analyzer.custom_analyzer.tokenizer", "my_tokenizer")
197+
.put("index.analysis.tokenizer.my_tokenizer.type", deprecatedName)
198+
.build();
199+
200+
try (CommonAnalysisPlugin commonAnalysisPlugin = new CommonAnalysisPlugin()) {
201+
Map<String, TokenizerFactory> tokenizers = createTestAnalysis(
202+
IndexSettingsModule.newIndexSettings("index", settings), settings, commonAnalysisPlugin).tokenizer;
203+
TokenizerFactory tokenizerFactory = tokenizers.get(deprecatedName);
204+
205+
Tokenizer tokenizer = tokenizerFactory.create();
206+
assertNotNull(tokenizer);
207+
if (expectWarning) {
208+
assertWarnings("The [" + deprecatedName + "] tokenizer name is deprecated and will be removed in a future version. "
209+
+ "Please change the tokenizer name to [" + replacement + "] instead.");
210+
}
211+
}
212+
}
129213
}

0 commit comments

Comments
 (0)