Skip to content

Commit fd564b1

Browse files
olcbeanDaveCTurner
authored andcommitted
Deprecate levenstein in favor of levenshtein (#27409)
Support both spellings thoughout 6.x, reporting the incorrect one as deprecated.
1 parent fadbe0d commit fd564b1

File tree

6 files changed

+66
-28
lines changed

6 files changed

+66
-28
lines changed

core/src/main/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGeneratorBuilder.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.elasticsearch.common.ParseField;
3232
import org.elasticsearch.common.io.stream.StreamInput;
3333
import org.elasticsearch.common.io.stream.StreamOutput;
34+
import org.elasticsearch.common.logging.DeprecationLogger;
35+
import org.elasticsearch.common.logging.Loggers;
3436
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
3537
import org.elasticsearch.common.xcontent.XContentBuilder;
3638
import org.elasticsearch.common.xcontent.XContentFactory;
@@ -45,6 +47,9 @@
4547

4648
public final class DirectCandidateGeneratorBuilder implements CandidateGenerator {
4749

50+
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(
51+
Loggers.getLogger(DirectCandidateGeneratorBuilder.class));
52+
4853
private static final String TYPE = "direct_generator";
4954

5055
public static final ParseField DIRECT_GENERATOR_FIELD = new ParseField(TYPE);
@@ -211,8 +216,8 @@ String sort() {
211216
* string distance for terms inside the index.
212217
* <li><code>damerau_levenshtein</code> - String distance algorithm
213218
* based on Damerau-Levenshtein algorithm.
214-
* <li><code>levenstein</code> - String distance algorithm based on
215-
* Levenstein edit distance algorithm.
219+
* <li><code>levenshtein</code> - String distance algorithm based on
220+
* Levenshtein edit distance algorithm.
216221
* <li><code>jarowinkler</code> - String distance algorithm based on
217222
* Jaro-Winkler algorithm.
218223
* <li><code>ngram</code> - String distance algorithm based on character
@@ -458,13 +463,16 @@ private static SuggestMode resolveSuggestMode(String suggestMode) {
458463
}
459464
}
460465

461-
private static StringDistance resolveDistance(String distanceVal) {
466+
static StringDistance resolveDistance(String distanceVal) {
462467
distanceVal = distanceVal.toLowerCase(Locale.US);
463468
if ("internal".equals(distanceVal)) {
464469
return DirectSpellChecker.INTERNAL_LEVENSHTEIN;
465470
} else if ("damerau_levenshtein".equals(distanceVal) || "damerauLevenshtein".equals(distanceVal)) {
466471
return new LuceneLevenshteinDistance();
467472
} else if ("levenstein".equals(distanceVal)) {
473+
DEPRECATION_LOGGER.deprecated("Deprecated distance [levenstein] used, replaced by [levenshtein]");
474+
return new LevensteinDistance();
475+
} else if ("levenshtein".equals(distanceVal)) {
468476
return new LevensteinDistance();
469477
// TODO Jaro and Winkler are 2 people - so apply same naming logic
470478
// as damerau_levenshtein

core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import org.elasticsearch.common.io.stream.StreamInput;
3131
import org.elasticsearch.common.io.stream.StreamOutput;
3232
import org.elasticsearch.common.io.stream.Writeable;
33+
import org.elasticsearch.common.logging.DeprecationLogger;
34+
import org.elasticsearch.common.logging.Loggers;
3335
import org.elasticsearch.common.xcontent.XContentBuilder;
3436
import org.elasticsearch.common.xcontent.XContentParser;
3537
import org.elasticsearch.index.query.QueryShardContext;
@@ -66,6 +68,9 @@
6668
* global options, but are only applicable for this suggestion.
6769
*/
6870
public class TermSuggestionBuilder extends SuggestionBuilder<TermSuggestionBuilder> {
71+
72+
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(Loggers.getLogger(TermSuggestionBuilder.class));
73+
6974
private static final String SUGGESTION_NAME = "term";
7075

7176
private SuggestMode suggestMode = SuggestMode.MISSING;
@@ -214,8 +219,8 @@ public SortBy sort() {
214219
* string distance for terms inside the index.
215220
* <li><code>damerau_levenshtein</code> - String distance algorithm based on
216221
* Damerau-Levenshtein algorithm.
217-
* <li><code>levenstein</code> - String distance algorithm based on
218-
* Levenstein edit distance algorithm.
222+
* <li><code>levenshtein</code> - String distance algorithm based on
223+
* Levenshtein edit distance algorithm.
219224
* <li><code>jarowinkler</code> - String distance algorithm based on
220225
* Jaro-Winkler algorithm.
221226
* <li><code>ngram</code> - String distance algorithm based on character
@@ -543,8 +548,8 @@ public StringDistance toLucene() {
543548
return new LuceneLevenshteinDistance();
544549
}
545550
},
546-
/** String distance algorithm based on Levenstein edit distance algorithm. */
547-
LEVENSTEIN {
551+
/** String distance algorithm based on Levenshtein edit distance algorithm. */
552+
LEVENSHTEIN {
548553
@Override
549554
public StringDistance toLucene() {
550555
return new LevensteinDistance();
@@ -584,7 +589,10 @@ public static StringDistanceImpl resolve(final String str) {
584589
case "damerauLevenshtein":
585590
return DAMERAU_LEVENSHTEIN;
586591
case "levenstein":
587-
return LEVENSTEIN;
592+
DEPRECATION_LOGGER.deprecated("Deprecated distance [levenstein] used, replaced by [levenshtein]");
593+
return LEVENSHTEIN;
594+
case "levenshtein":
595+
return LEVENSHTEIN;
588596
case "ngram":
589597
return NGRAM;
590598
case "jarowinkler":

core/src/test/java/org/elasticsearch/search/suggest/phrase/DirectCandidateGeneratorTests.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919

2020
package org.elasticsearch.search.suggest.phrase;
2121

22+
import org.apache.lucene.search.spell.DirectSpellChecker;
23+
import org.apache.lucene.search.spell.JaroWinklerDistance;
24+
import org.apache.lucene.search.spell.LevensteinDistance;
25+
import org.apache.lucene.search.spell.LuceneLevenshteinDistance;
26+
import org.apache.lucene.search.spell.NGramDistance;
2227
import org.elasticsearch.common.ParsingException;
2328
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
2429
import org.elasticsearch.common.xcontent.ToXContent;
@@ -38,6 +43,8 @@
3843
import java.util.function.Supplier;
3944

4045
import static org.elasticsearch.test.EqualsHashCodeTestUtils.checkEqualsAndHashCode;
46+
import static org.hamcrest.Matchers.equalTo;
47+
import static org.hamcrest.core.IsInstanceOf.instanceOf;
4148

4249
public class DirectCandidateGeneratorTests extends ESTestCase {
4350
private static final int NUMBER_OF_RUNS = 20;
@@ -65,6 +72,22 @@ public void testEqualsAndHashcode() throws IOException {
6572
}
6673
}
6774

75+
public void testFromString() {
76+
assertThat(DirectCandidateGeneratorBuilder.resolveDistance("internal"), equalTo(DirectSpellChecker.INTERNAL_LEVENSHTEIN));
77+
assertThat(DirectCandidateGeneratorBuilder.resolveDistance("damerau_levenshtein"), instanceOf(LuceneLevenshteinDistance.class));
78+
assertThat(DirectCandidateGeneratorBuilder.resolveDistance("levenshtein"), instanceOf(LevensteinDistance.class));
79+
assertThat(DirectCandidateGeneratorBuilder.resolveDistance("jaroWinkler"), instanceOf(JaroWinklerDistance.class));
80+
assertThat(DirectCandidateGeneratorBuilder.resolveDistance("ngram"), instanceOf(NGramDistance.class));
81+
82+
expectThrows(IllegalArgumentException.class, () -> DirectCandidateGeneratorBuilder.resolveDistance("doesnt_exist"));
83+
expectThrows(NullPointerException.class, () -> DirectCandidateGeneratorBuilder.resolveDistance(null));
84+
}
85+
86+
public void testLevensteinDeprecation() {
87+
assertThat(DirectCandidateGeneratorBuilder.resolveDistance("levenstein"), instanceOf(LevensteinDistance.class));
88+
assertWarnings("Deprecated distance [levenstein] used, replaced by [levenshtein]");
89+
}
90+
6891
private static DirectCandidateGeneratorBuilder mutate(DirectCandidateGeneratorBuilder original) throws IOException {
6992
DirectCandidateGeneratorBuilder mutation = copy(original);
7093
List<Supplier<DirectCandidateGeneratorBuilder>> mutators = new ArrayList<>();
@@ -89,7 +112,7 @@ private static DirectCandidateGeneratorBuilder mutate(DirectCandidateGeneratorBu
89112
mutators.add(() -> mutation.preFilter(original.preFilter() == null ? "preFilter" : original.preFilter() + "_other"));
90113
mutators.add(() -> mutation.sort(original.sort() == null ? "score" : original.sort() + "_other"));
91114
mutators.add(
92-
() -> mutation.stringDistance(original.stringDistance() == null ? "levenstein" : original.stringDistance() + "_other"));
115+
() -> mutation.stringDistance(original.stringDistance() == null ? "levenshtein" : original.stringDistance() + "_other"));
93116
mutators.add(() -> mutation.suggestMode(original.suggestMode() == null ? "missing" : original.suggestMode() + "_other"));
94117
return randomFrom(mutators).get();
95118
}
@@ -189,7 +212,7 @@ public static DirectCandidateGeneratorBuilder randomCandidateGenerator() {
189212
maybeSet(generator::postFilter, randomAlphaOfLengthBetween(1, 20));
190213
maybeSet(generator::size, randomIntBetween(1, 20));
191214
maybeSet(generator::sort, randomFrom("score", "frequency"));
192-
maybeSet(generator::stringDistance, randomFrom("internal", "damerau_levenshtein", "levenstein", "jarowinkler", "ngram"));
215+
maybeSet(generator::stringDistance, randomFrom("internal", "damerau_levenshtein", "levenshtein", "jarowinkler", "ngram"));
193216
maybeSet(generator::suggestMode, randomFrom("missing", "popular", "always"));
194217
return generator;
195218
}

core/src/test/java/org/elasticsearch/search/suggest/term/StringDistanceImplTests.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
package org.elasticsearch.search.suggest.term;
2121

2222
import org.elasticsearch.common.io.stream.AbstractWriteableEnumTestCase;
23+
import org.elasticsearch.search.suggest.term.TermSuggestionBuilder.StringDistanceImpl;
2324

2425
import java.io.IOException;
2526

26-
import static org.elasticsearch.search.suggest.term.TermSuggestionBuilder.StringDistanceImpl;
2727
import static org.hamcrest.Matchers.equalTo;
2828

2929
/**
@@ -38,7 +38,7 @@ public StringDistanceImplTests() {
3838
public void testValidOrdinals() {
3939
assertThat(StringDistanceImpl.INTERNAL.ordinal(), equalTo(0));
4040
assertThat(StringDistanceImpl.DAMERAU_LEVENSHTEIN.ordinal(), equalTo(1));
41-
assertThat(StringDistanceImpl.LEVENSTEIN.ordinal(), equalTo(2));
41+
assertThat(StringDistanceImpl.LEVENSHTEIN.ordinal(), equalTo(2));
4242
assertThat(StringDistanceImpl.JAROWINKLER.ordinal(), equalTo(3));
4343
assertThat(StringDistanceImpl.NGRAM.ordinal(), equalTo(4));
4444
}
@@ -47,28 +47,27 @@ public void testValidOrdinals() {
4747
public void testFromString() {
4848
assertThat(StringDistanceImpl.resolve("internal"), equalTo(StringDistanceImpl.INTERNAL));
4949
assertThat(StringDistanceImpl.resolve("damerau_levenshtein"), equalTo(StringDistanceImpl.DAMERAU_LEVENSHTEIN));
50-
assertThat(StringDistanceImpl.resolve("levenstein"), equalTo(StringDistanceImpl.LEVENSTEIN));
50+
assertThat(StringDistanceImpl.resolve("levenshtein"), equalTo(StringDistanceImpl.LEVENSHTEIN));
5151
assertThat(StringDistanceImpl.resolve("jarowinkler"), equalTo(StringDistanceImpl.JAROWINKLER));
5252
assertThat(StringDistanceImpl.resolve("ngram"), equalTo(StringDistanceImpl.NGRAM));
53+
5354
final String doesntExist = "doesnt_exist";
54-
try {
55-
StringDistanceImpl.resolve(doesntExist);
56-
fail("StringDistanceImpl should not have an element " + doesntExist);
57-
} catch (IllegalArgumentException e) {
58-
}
59-
try {
60-
StringDistanceImpl.resolve(null);
61-
fail("StringDistanceImpl.resolve on a null value should throw an exception.");
62-
} catch (NullPointerException e) {
63-
assertThat(e.getMessage(), equalTo("Input string is null"));
64-
}
55+
expectThrows(IllegalArgumentException.class, () -> StringDistanceImpl.resolve(doesntExist));
56+
57+
NullPointerException e = expectThrows(NullPointerException.class, () -> StringDistanceImpl.resolve(null));
58+
assertThat(e.getMessage(), equalTo("Input string is null"));
59+
}
60+
61+
public void testLevensteinDeprecation() {
62+
assertThat(StringDistanceImpl.resolve("levenstein"), equalTo(StringDistanceImpl.LEVENSHTEIN));
63+
assertWarnings("Deprecated distance [levenstein] used, replaced by [levenshtein]");
6564
}
6665

6766
@Override
6867
public void testWriteTo() throws IOException {
6968
assertWriteToStream(StringDistanceImpl.INTERNAL, 0);
7069
assertWriteToStream(StringDistanceImpl.DAMERAU_LEVENSHTEIN, 1);
71-
assertWriteToStream(StringDistanceImpl.LEVENSTEIN, 2);
70+
assertWriteToStream(StringDistanceImpl.LEVENSHTEIN, 2);
7271
assertWriteToStream(StringDistanceImpl.JAROWINKLER, 3);
7372
assertWriteToStream(StringDistanceImpl.NGRAM, 4);
7473
}
@@ -77,7 +76,7 @@ public void testWriteTo() throws IOException {
7776
public void testReadFrom() throws IOException {
7877
assertReadFromStream(0, StringDistanceImpl.INTERNAL);
7978
assertReadFromStream(1, StringDistanceImpl.DAMERAU_LEVENSHTEIN);
80-
assertReadFromStream(2, StringDistanceImpl.LEVENSTEIN);
79+
assertReadFromStream(2, StringDistanceImpl.LEVENSHTEIN);
8180
assertReadFromStream(3, StringDistanceImpl.JAROWINKLER);
8281
assertReadFromStream(4, StringDistanceImpl.NGRAM);
8382
}

core/src/test/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilderTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ private static StringDistanceImpl randomStringDistance() {
9999
switch (randomVal) {
100100
case 0: return StringDistanceImpl.INTERNAL;
101101
case 1: return StringDistanceImpl.DAMERAU_LEVENSHTEIN;
102-
case 2: return StringDistanceImpl.LEVENSTEIN;
102+
case 2: return StringDistanceImpl.LEVENSHTEIN;
103103
case 3: return StringDistanceImpl.JAROWINKLER;
104104
case 4: return StringDistanceImpl.NGRAM;
105105
default: throw new IllegalArgumentException("No string distance algorithm with an ordinal of " + randomVal);

docs/reference/search/suggesters/term-suggest.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ doesn't take the query into account that is part of request.
116116
for comparing string distance for terms inside the index.
117117
`damerau_levenshtein` - String distance algorithm based on
118118
Damerau-Levenshtein algorithm.
119-
`levenstein` - String distance algorithm based on Levenstein edit distance
119+
`levenshtein` - String distance algorithm based on Levenshtein edit distance
120120
algorithm.
121121
`jarowinkler` - String distance algorithm based on Jaro-Winkler algorithm.
122122
`ngram` - String distance algorithm based on character n-grams.

0 commit comments

Comments
 (0)