Skip to content

Commit 714aaa4

Browse files
committed
CompletionFieldMapper should use index name instead of full name
Fixes elastic#3669
1 parent 507b6a6 commit 714aaa4

File tree

3 files changed

+53
-46
lines changed

3 files changed

+53
-46
lines changed

src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public Builder preservePositionIncrements(boolean preservePositionIncrements) {
112112
this.preservePositionIncrements = preservePositionIncrements;
113113
return this;
114114
}
115-
115+
116116
public Builder maxInputLength(int maxInputLength) {
117117
if (maxInputLength <= 0) {
118118
throw new ElasticSearchIllegalArgumentException(Fields.MAX_INPUT_LENGTH + " must be > 0 but was [" + maxInputLength + "]");
@@ -175,7 +175,7 @@ public static class TypeParser implements Mapper.TypeParser {
175175
private NamedAnalyzer getNamedAnalyzer(ParserContext parserContext, String name) {
176176
NamedAnalyzer analyzer = parserContext.analysisService().analyzer(name);
177177
if (analyzer == null) {
178-
throw new ElasticSearchIllegalArgumentException("Can't find default or mapped analyzer with name [" + name +"]");
178+
throw new ElasticSearchIllegalArgumentException("Can't find default or mapped analyzer with name [" + name + "]");
179179
}
180180
return analyzer;
181181
}
@@ -280,21 +280,21 @@ public Field getCompletionField(String input, BytesRef payload) {
280280
final String originalInput = input;
281281
if (input.length() > maxInputLength) {
282282
final int len = correctSubStringLen(input, Math.min(maxInputLength, input.length()));
283-
input = input.substring(0, len);
283+
input = input.substring(0, len);
284284
}
285285
for (int i = 0; i < input.length(); i++) {
286286
if (isReservedChar(input.charAt(i))) {
287287
throw new ElasticSearchIllegalArgumentException("Illegal input [" + originalInput + "] UTF-16 codepoint [0x"
288-
+ Integer.toHexString((int) input.charAt(i)).toUpperCase(Locale.ROOT)
288+
+ Integer.toHexString((int) input.charAt(i)).toUpperCase(Locale.ROOT)
289289
+ "] at position " + i + " is a reserved character");
290290
}
291291
}
292-
return new SuggestField(names().fullName(), input, this.fieldType, payload, analyzingSuggestLookupProvider);
292+
return new SuggestField(names.indexName(), input, this.fieldType, payload, analyzingSuggestLookupProvider);
293293
}
294-
294+
295295
public static int correctSubStringLen(String input, int len) {
296-
if (Character.isHighSurrogate(input.charAt(len-1))) {
297-
assert input.length() >= len+1 && Character.isLowSurrogate(input.charAt(len));
296+
if (Character.isHighSurrogate(input.charAt(len - 1))) {
297+
assert input.length() >= len + 1 && Character.isLowSurrogate(input.charAt(len));
298298
return len + 1;
299299
}
300300
return len;
@@ -308,7 +308,7 @@ public BytesRef buildPayload(BytesRef surfaceForm, long weight, BytesRef payload
308308
private static final class SuggestField extends Field {
309309
private final BytesRef payload;
310310
private final CompletionTokenStream.ToFiniteStrings toFiniteStrings;
311-
311+
312312
public SuggestField(String name, Reader value, FieldType type, BytesRef payload, CompletionTokenStream.ToFiniteStrings toFiniteStrings) {
313313
super(name, value, type);
314314
this.payload = payload;
@@ -342,7 +342,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
342342
builder.field(Fields.PAYLOADS, this.payloads);
343343
builder.field(Fields.PRESERVE_SEPARATORS, this.preserveSeparators);
344344
builder.field(Fields.PRESERVE_POSITION_INCREMENTS, this.preservePositionIncrements);
345-
builder.field(Fields.MAX_INPUT_LENGTH, this.maxInputLength);
345+
builder.field(Fields.MAX_INPUT_LENGTH, this.maxInputLength);
346346
return builder.endObject();
347347
}
348348

@@ -379,27 +379,27 @@ public String value(Object value) {
379379
public boolean isStoringPayloads() {
380380
return payloads;
381381
}
382-
382+
383383
@Override
384384
public void merge(Mapper mergeWith, MergeContext mergeContext) throws MergeMappingException {
385385
super.merge(mergeWith, mergeContext);
386386
CompletionFieldMapper fieldMergeWith = (CompletionFieldMapper) mergeWith;
387387
if (payloads != fieldMergeWith.payloads) {
388388
mergeContext.addConflict("mapper [" + names.fullName() + "] has different payload values");
389389
}
390-
if (preservePositionIncrements != fieldMergeWith.preservePositionIncrements) {
390+
if (preservePositionIncrements != fieldMergeWith.preservePositionIncrements) {
391391
mergeContext.addConflict("mapper [" + names.fullName() + "] has different 'preserve_position_increments' values");
392392
}
393-
if (preserveSeparators != fieldMergeWith.preserveSeparators) {
393+
if (preserveSeparators != fieldMergeWith.preserveSeparators) {
394394
mergeContext.addConflict("mapper [" + names.fullName() + "] has different 'preserve_separators' values");
395395
}
396396
if (!mergeContext.mergeFlags().simulate()) {
397397
this.maxInputLength = fieldMergeWith.maxInputLength;
398398
}
399399
}
400-
400+
401401
private static final char END_LABEL = 0x00;
402-
402+
403403
// this should be package private but our tests don't allow it.
404404
public static boolean isReservedChar(char character) {
405405
/* we also use 0xFF as a SEP_LABEL in the suggester but it's not valid UTF-8 so no need to check.

src/main/java/org/elasticsearch/search/suggest/completion/AnalyzingCompletionLookupProvider.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@
3131
import org.apache.lucene.util.BytesRef;
3232
import org.apache.lucene.util.IOUtils;
3333
import org.apache.lucene.util.IntsRef;
34-
import org.apache.lucene.util.fst.*;
34+
import org.apache.lucene.util.fst.ByteSequenceOutputs;
35+
import org.apache.lucene.util.fst.FST;
36+
import org.apache.lucene.util.fst.PairOutputs;
3537
import org.apache.lucene.util.fst.PairOutputs.Pair;
38+
import org.apache.lucene.util.fst.PositiveIntOutputs;
3639
import org.elasticsearch.common.regex.Regex;
3740
import org.elasticsearch.index.mapper.FieldMapper;
3841
import org.elasticsearch.search.suggest.completion.Completion090PostingsFormat.CompletionLookupProvider;
@@ -50,10 +53,10 @@ public class AnalyzingCompletionLookupProvider extends CompletionLookupProvider
5053

5154
private static final int MAX_SURFACE_FORMS_PER_ANALYZED_FORM = 256;
5255
private static final int MAX_GRAPH_EXPANSIONS = -1;
53-
56+
5457
public static final String CODEC_NAME = "analyzing";
5558
public static final int CODEC_VERSION = 1;
56-
59+
5760
private boolean preserveSep;
5861
private boolean preservePositionIncrements;
5962
private int maxSurfaceFormsPerAnalyzedForm;
@@ -84,6 +87,7 @@ public FieldsConsumer consumer(final IndexOutput output) throws IOException {
8487
CodecUtil.writeHeader(output, CODEC_NAME, CODEC_VERSION);
8588
return new FieldsConsumer() {
8689
private Map<FieldInfo, Long> fieldOffsets = new HashMap<FieldInfo, Long>();
90+
8791
@Override
8892
public void close() throws IOException {
8993
try { /*
@@ -179,7 +183,7 @@ public void addPosition(int position, BytesRef payload, int startOffset, int end
179183
analyzingSuggestLookupProvider.parsePayload(payload, spare);
180184
builder.addSurface(spare.surfaceForm, spare.payload, spare.weight);
181185
// multi fields have the same surface form so we sum up here
182-
maxAnalyzedPathsForOneInput = Math.max(maxAnalyzedPathsForOneInput, position+1);
186+
maxAnalyzedPathsForOneInput = Math.max(maxAnalyzedPathsForOneInput, position + 1);
183187
}
184188

185189
@Override
@@ -189,7 +193,9 @@ public void finishDoc() throws IOException {
189193
public int getMaxAnalyzedPathsForOneInput() {
190194
return maxAnalyzedPathsForOneInput;
191195
}
192-
};
196+
}
197+
198+
;
193199

194200

195201
@Override
@@ -225,11 +231,11 @@ public LookupFactory load(IndexInput input) throws IOException {
225231
return new LookupFactory() {
226232
@Override
227233
public Lookup getLookup(FieldMapper<?> mapper, CompletionSuggestionContext suggestionContext) {
228-
AnalyzingSuggestHolder analyzingSuggestHolder = lookupMap.get(mapper.names().fullName());
234+
AnalyzingSuggestHolder analyzingSuggestHolder = lookupMap.get(mapper.names().indexName());
229235
if (analyzingSuggestHolder == null) {
230236
return null;
231237
}
232-
int flags = analyzingSuggestHolder.preserveSep? XAnalyzingSuggester.PRESERVE_SEP : 0;
238+
int flags = analyzingSuggestHolder.preserveSep ? XAnalyzingSuggester.PRESERVE_SEP : 0;
233239

234240
XAnalyzingSuggester suggester;
235241
if (suggestionContext.isFuzzy()) {
@@ -251,14 +257,14 @@ public Lookup getLookup(FieldMapper<?> mapper, CompletionSuggestionContext sugge
251257
}
252258

253259
@Override
254-
public CompletionStats stats(String ... fields) {
260+
public CompletionStats stats(String... fields) {
255261
long sizeInBytes = 0;
256262
TObjectLongHashMap<String> completionFields = null;
257-
if (fields != null && fields.length > 0) {
263+
if (fields != null && fields.length > 0) {
258264
completionFields = new TObjectLongHashMap<String>(fields.length);
259265
}
260266

261-
for (Map.Entry<String, AnalyzingSuggestHolder> entry: lookupMap.entrySet()) {
267+
for (Map.Entry<String, AnalyzingSuggestHolder> entry : lookupMap.entrySet()) {
262268
sizeInBytes += entry.getValue().fst.sizeInBytes();
263269
if (fields == null || fields.length == 0) {
264270
continue;

src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchTests.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
2222
import com.google.common.collect.Lists;
23+
import org.elasticsearch.AbstractSharedClusterTest;
2324
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
2425
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
2526
import org.elasticsearch.action.admin.indices.optimize.OptimizeResponse;
@@ -39,7 +40,6 @@
3940
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
4041
import org.elasticsearch.search.suggest.completion.CompletionSuggestionFuzzyBuilder;
4142
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
42-
import org.elasticsearch.AbstractSharedClusterTest;
4343
import org.junit.Test;
4444

4545
import java.io.IOException;
@@ -370,6 +370,7 @@ public void testThatUpgradeToMultiFieldWorks() throws Exception {
370370
.startObject(TYPE).startObject("properties")
371371
.startObject(FIELD)
372372
.field("type", "multi_field")
373+
.field("path", "just_name")
373374
.startObject("fields")
374375
.startObject(FIELD).field("type", "string").endObject()
375376
.startObject("suggest").field("type", "completion").field("index_analyzer", "simple").field("search_analyzer", "simple").endObject()
@@ -381,15 +382,15 @@ public void testThatUpgradeToMultiFieldWorks() throws Exception {
381382
assertThat(putMappingResponse.isAcknowledged(), is(true));
382383

383384
SuggestResponse suggestResponse = client().prepareSuggest(INDEX).addSuggestion(
384-
new CompletionSuggestionBuilder("suggs").field(FIELD + ".suggest").text("f").size(10)
385+
new CompletionSuggestionBuilder("suggs").field("suggest").text("f").size(10)
385386
).execute().actionGet();
386387
assertSuggestions(suggestResponse, "suggs");
387388

388389
client().prepareIndex(INDEX, TYPE, "1").setRefresh(true).setSource(jsonBuilder().startObject().field(FIELD, "Foo Fighters").endObject()).get();
389390
waitForRelocation(ClusterHealthStatus.GREEN);
390391

391392
SuggestResponse afterReindexingResponse = client().prepareSuggest(INDEX).addSuggestion(
392-
new CompletionSuggestionBuilder("suggs").field(FIELD + ".suggest").text("f").size(10)
393+
new CompletionSuggestionBuilder("suggs").field("suggest").text("f").size(10)
393394
).execute().actionGet();
394395
assertSuggestions(afterReindexingResponse, "suggs", "Foo Fighters");
395396
}
@@ -684,7 +685,7 @@ private void createData(boolean optimize) throws IOException, InterruptedExcepti
684685
client().admin().indices().prepareOptimize(INDEX).execute().actionGet();
685686
}
686687
}
687-
688+
688689
@Test // see #3555
689690
public void testPrunedSegments() throws IOException {
690691
createIndexAndMappingAndSettings(settingsBuilder().put(SETTING_NUMBER_OF_SHARDS, 1).put(SETTING_NUMBER_OF_REPLICAS, 0), "standard", "standard", false, false, false);
@@ -696,43 +697,43 @@ public void testPrunedSegments() throws IOException {
696697
).get();
697698
client().prepareIndex(INDEX, TYPE, "2").setSource(jsonBuilder()
698699
.startObject()
699-
.field("somefield", "somevalue")
700+
.field("somefield", "somevalue")
700701
.endObject()
701702
).get(); // we have 2 docs in a segment...
702703
OptimizeResponse actionGet = client().admin().indices().prepareOptimize().setFlush(true).setMaxNumSegments(1).setRefresh(true).execute().actionGet();
703704
assertNoFailures(actionGet);
704705
// update the first one and then merge.. the target segment will have no value in FIELD
705706
client().prepareIndex(INDEX, TYPE, "1").setSource(jsonBuilder()
706707
.startObject()
707-
.field("somefield", "somevalue")
708+
.field("somefield", "somevalue")
708709
.endObject()
709710
).get();
710711
actionGet = client().admin().indices().prepareOptimize().setFlush(true).setMaxNumSegments(1).setRefresh(true).execute().actionGet();
711712
assertNoFailures(actionGet);
712713

713714
assertSuggestions("b");
714715
assertThat(2l, equalTo(client().prepareCount(INDEX).get().getCount()));
715-
for(IndexShardSegments seg : client().admin().indices().prepareSegments().get().getIndices().get(INDEX)) {
716+
for (IndexShardSegments seg : client().admin().indices().prepareSegments().get().getIndices().get(INDEX)) {
716717
ShardSegments[] shards = seg.getShards();
717718
for (ShardSegments shardSegments : shards) {
718719
assertThat(1, equalTo(shardSegments.getSegments().size()));
719720
}
720721
}
721722
}
722-
723+
723724
@Test
724725
public void testMaxFieldLength() throws IOException {
725726
client().admin().indices().prepareCreate(INDEX).get();
726727
int iters = atLeast(10);
727728
for (int i = 0; i < iters; i++) {
728729
int len = between(3, 50);
729-
String str = replaceReservedChars(randomRealisticUnicodeOfCodepointLengthBetween(len+1, atLeast(len + 2)), (char)0x01);
730+
String str = replaceReservedChars(randomRealisticUnicodeOfCodepointLengthBetween(len + 1, atLeast(len + 2)), (char) 0x01);
730731
ElasticsearchAssertions.assertAcked(client().admin().indices().preparePutMapping(INDEX).setType(TYPE).setSource(jsonBuilder().startObject()
731732
.startObject(TYPE).startObject("properties")
732733
.startObject(FIELD)
733734
.field("type", "completion")
734735
.field("max_input_len", len)
735-
// upgrade mapping each time
736+
// upgrade mapping each time
736737
.field("analyzer", "keyword")
737738
.endObject()
738739
.endObject().endObject()
@@ -748,14 +749,14 @@ public void testMaxFieldLength() throws IOException {
748749
assertSuggestions(str.substring(0, prefixLen), "foobar");
749750
if (len + 1 < str.length()) {
750751
assertSuggestions(str.substring(0, CompletionFieldMapper.correctSubStringLen(str,
751-
len + (Character.isHighSurrogate(str.charAt(len-1)) ? 2 : 1))));
752+
len + (Character.isHighSurrogate(str.charAt(len - 1)) ? 2 : 1))));
752753
}
753-
}
754+
}
754755
}
755-
756+
756757
@Test
757758
// see #3596
758-
public void testVeryLongInput() throws IOException {
759+
public void testVeryLongInput() throws IOException {
759760
client().admin().indices().prepareCreate(INDEX).get();
760761
ElasticsearchAssertions.assertAcked(client().admin().indices().preparePutMapping(INDEX).setType(TYPE).setSource(jsonBuilder().startObject()
761762
.startObject(TYPE).startObject("properties")
@@ -766,19 +767,19 @@ public void testVeryLongInput() throws IOException {
766767
.endObject()));
767768
ensureYellow();
768769
// can cause stack overflow without the default max_input_len
769-
String longString = replaceReservedChars(randomRealisticUnicodeOfLength(atLeast(5000)), (char)0x01);
770+
String longString = replaceReservedChars(randomRealisticUnicodeOfLength(atLeast(5000)), (char) 0x01);
770771
client().prepareIndex(INDEX, TYPE, "1").setSource(jsonBuilder()
771772
.startObject().startObject(FIELD)
772773
.startArray("input").value(longString).endArray()
773774
.field("output", "foobar")
774775
.endObject().endObject()
775776
).setRefresh(true).get();
776-
777+
777778
}
778-
779+
779780
// see #3648
780781
@Test(expected = MapperParsingException.class)
781-
public void testReservedChars() throws IOException {
782+
public void testReservedChars() throws IOException {
782783
client().admin().indices().prepareCreate(INDEX).get();
783784
ElasticsearchAssertions.assertAcked(client().admin().indices().preparePutMapping(INDEX).setType(TYPE).setSource(jsonBuilder().startObject()
784785
.startObject(TYPE).startObject("properties")
@@ -789,16 +790,16 @@ public void testReservedChars() throws IOException {
789790
.endObject()));
790791
ensureYellow();
791792
// can cause stack overflow without the default max_input_len
792-
String string = "foo" + (char)0x00 + "bar";
793+
String string = "foo" + (char) 0x00 + "bar";
793794
client().prepareIndex(INDEX, TYPE, "1").setSource(jsonBuilder()
794795
.startObject().startObject(FIELD)
795796
.startArray("input").value(string).endArray()
796797
.field("output", "foobar")
797798
.endObject().endObject()
798799
).setRefresh(true).get();
799-
800+
800801
}
801-
802+
802803
private static String replaceReservedChars(String input, char replacement) {
803804
char[] charArray = input.toCharArray();
804805
for (int i = 0; i < charArray.length; i++) {

0 commit comments

Comments
 (0)