Skip to content

Commit

Permalink
Store offsets in index prefix fields when stored in the parent field (#…
Browse files Browse the repository at this point in the history
…29067)

The index prefix field is normally indexed as docs-only, given that it cannot
be used in phrases.  However, in the case that the parent field has been indexed
with offsets, or has term-vector offsets, we should also store this in the index
prefix field for highlighting.

Note that this commit does not implement highlighting on prefix fields, but
rather ensures that future work can implement this without a backwards-break
in index data.

Closes #28994
  • Loading branch information
romseygeek authored Mar 16, 2018
1 parent 42c7c75 commit 986e518
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.ngram.EdgeNGramTokenFilter;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
Expand Down Expand Up @@ -152,11 +153,20 @@ public TextFieldMapper build(BuilderContext context) {
fieldType.setSearchQuoteAnalyzer(new NamedAnalyzer(fieldType.searchQuoteAnalyzer(), positionIncrementGap));
}
setupFieldType(context);
if (prefixFieldType != null && fieldType().isSearchable() == false) {
throw new IllegalArgumentException("Cannot set index_prefix on unindexed field [" + name() + "]");
PrefixFieldMapper prefixMapper = null;
if (prefixFieldType != null) {
if (fieldType().isSearchable() == false) {
throw new IllegalArgumentException("Cannot set index_prefix on unindexed field [" + name() + "]");
}
if (fieldType.indexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) {
prefixFieldType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
}
if (fieldType.storeTermVectorOffsets()) {
prefixFieldType.setStoreTermVectorOffsets(true);
}
prefixFieldType.setAnalyzer(fieldType.indexAnalyzer());
prefixMapper = new PrefixFieldMapper(prefixFieldType, context.indexSettings());
}
PrefixFieldMapper prefixMapper = prefixFieldType == null ? null
: new PrefixFieldMapper(prefixFieldType.setAnalyzer(fieldType.indexAnalyzer()), context.indexSettings());
return new TextFieldMapper(
name, fieldType, defaultFieldType, positionIncrementGap, prefixMapper,
context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.elasticsearch.index.mapper;

import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
Expand Down Expand Up @@ -595,6 +596,80 @@ public void testEmptyName() throws IOException {
assertThat(e.getMessage(), containsString("name cannot be empty string"));
}

public void testIndexPrefixIndexTypes() throws IOException {
QueryShardContext queryShardContext = indexService.newQueryShardContext(
randomInt(20), null, () -> {
throw new UnsupportedOperationException();
}, null);

{
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field")
.field("type", "text")
.field("analyzer", "english")
.startObject("index_prefix").endObject()
.field("index_options", "offsets")
.endObject().endObject().endObject().endObject().string();

DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping));

FieldMapper prefix = mapper.mappers().getMapper("field._index_prefix");
FieldType ft = prefix.fieldType;
assertEquals(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, ft.indexOptions());
}

{
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field")
.field("type", "text")
.field("analyzer", "english")
.startObject("index_prefix").endObject()
.field("index_options", "positions")
.endObject().endObject().endObject().endObject().string();

DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping));

FieldMapper prefix = mapper.mappers().getMapper("field._index_prefix");
FieldType ft = prefix.fieldType;
assertEquals(IndexOptions.DOCS, ft.indexOptions());
assertFalse(ft.storeTermVectors());
}

{
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field")
.field("type", "text")
.field("analyzer", "english")
.startObject("index_prefix").endObject()
.field("term_vector", "with_positions_offsets")
.endObject().endObject().endObject().endObject().string();

DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping));

FieldMapper prefix = mapper.mappers().getMapper("field._index_prefix");
FieldType ft = prefix.fieldType;
assertEquals(IndexOptions.DOCS, ft.indexOptions());
assertTrue(ft.storeTermVectorOffsets());
}

{
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field")
.field("type", "text")
.field("analyzer", "english")
.startObject("index_prefix").endObject()
.field("term_vector", "with_positions")
.endObject().endObject().endObject().endObject().string();

DocumentMapper mapper = parser.parse("type", new CompressedXContent(mapping));

FieldMapper prefix = mapper.mappers().getMapper("field._index_prefix");
FieldType ft = prefix.fieldType;
assertEquals(IndexOptions.DOCS, ft.indexOptions());
assertFalse(ft.storeTermVectorOffsets());
}
}

public void testIndexPrefixMapping() throws IOException {

QueryShardContext queryShardContext = indexService.newQueryShardContext(
Expand Down

0 comments on commit 986e518

Please sign in to comment.