Skip to content

Backport support for runtime fields #62015

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,16 @@ public class MetadataIndexUpgradeService {
private final MapperRegistry mapperRegistry;
private final IndexScopedSettings indexScopedSettings;
private final SystemIndices systemIndices;
private final ScriptService scriptService;

public MetadataIndexUpgradeService(Settings settings, NamedXContentRegistry xContentRegistry, MapperRegistry mapperRegistry,
IndexScopedSettings indexScopedSettings, SystemIndices systemIndices) {
IndexScopedSettings indexScopedSettings, SystemIndices systemIndices, ScriptService scriptService) {
this.settings = settings;
this.xContentRegistry = xContentRegistry;
this.mapperRegistry = mapperRegistry;
this.indexScopedSettings = indexScopedSettings;
this.systemIndices = systemIndices;
this.scriptService = scriptService;
}

/**
Expand Down Expand Up @@ -188,7 +190,7 @@ public Set<Entry<String, NamedAnalyzer>> entrySet() {
try (IndexAnalyzers fakeIndexAnalzyers =
new IndexAnalyzers(analyzerMap, analyzerMap, analyzerMap)) {
MapperService mapperService = new MapperService(indexSettings, fakeIndexAnalzyers, xContentRegistry, similarityService,
mapperRegistry, () -> null, () -> false);
mapperRegistry, () -> null, () -> false, scriptService);
mapperService.merge(indexMetadata, MapperService.MergeReason.MAPPING_RECOVERY);
}
} catch (Exception ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ public MapperService newIndexMapperService(NamedXContentRegistry xContentRegistr
ScriptService scriptService) throws IOException {
return new MapperService(indexSettings, analysisRegistry.build(indexSettings), xContentRegistry,
new SimilarityService(indexSettings, scriptService, similarities), mapperRegistry,
() -> { throw new UnsupportedOperationException("no index query shard context available"); }, () -> false);
() -> { throw new UnsupportedOperationException("no index query shard context available"); }, () -> false, scriptService);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,14 @@ public IndexService(
assert indexAnalyzers != null;
this.mapperService = new MapperService(indexSettings, indexAnalyzers, xContentRegistry, similarityService, mapperRegistry,
// we parse all percolator queries as they would be parsed on shard 0
() -> newQueryShardContext(0, null, System::currentTimeMillis, null), idFieldDataEnabled);
() -> newQueryShardContext(0, null, System::currentTimeMillis, null), idFieldDataEnabled, scriptService);
this.indexFieldData = new IndexFieldDataService(indexSettings, indicesFieldDataCache, circuitBreakerService, mapperService);
if (indexSettings.getIndexSortConfig().hasIndexSort()) {
// we delay the actual creation of the sort order for this index because the mapping has not been merged yet.
// The sort order is validated right after the merge of the mapping later in the process.
this.indexSortSupplier = () -> indexSettings.getIndexSortConfig().buildIndexSort(
mapperService::fieldType,
fieldType -> indexFieldData.getForField(fieldType, indexFieldData.index().getName(), () -> {
throw new UnsupportedOperationException("search lookup not available for index sorting");
})
(fieldType, searchLookup) -> indexFieldData.getForField(fieldType, indexFieldData.index().getName(), searchLookup)
);
} else {
this.indexSortSupplier = () -> null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.search.MultiValueMode;
import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.search.sort.SortOrder;

import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
* Holds all the information that is used to build the sort order of an index.
Expand Down Expand Up @@ -181,7 +184,7 @@ public boolean hasPrimarySortOnField(String field) {
* or returns null if this index has no sort.
*/
public Sort buildIndexSort(Function<String, MappedFieldType> fieldTypeLookup,
Function<MappedFieldType, IndexFieldData<?>> fieldDataLookup) {
BiFunction<MappedFieldType, Supplier<SearchLookup>, IndexFieldData<?>> fieldDataLookup) {
if (hasIndexSort() == false) {
return null;
}
Expand All @@ -200,7 +203,9 @@ public Sort buildIndexSort(Function<String, MappedFieldType> fieldTypeLookup,
}
IndexFieldData<?> fieldData;
try {
fieldData = fieldDataLookup.apply(ft);
fieldData = fieldDataLookup.apply(ft, () -> {
throw new UnsupportedOperationException("index sorting not supported on runtime field [" + ft.name() + "]");
});
} catch (Exception e) {
throw new IllegalArgumentException("docvalues not found for index sort field:[" + sortSpec.field + "]", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,25 +481,30 @@ protected void resize(int newSize) {
public int size() {
return count;
}

}

public static final class Strings extends BinaryScriptDocValues<String> {

public static class Strings extends BinaryScriptDocValues<String> {
public Strings(SortedBinaryDocValues in) {
super(in);
}

@Override
public String get(int index) {
public final String get(int index) {
if (count == 0) {
throw new IllegalStateException("A document doesn't have a value for a field! " +
"Use doc[<field>].size()==0 to check if a document is missing a field!");
}
return values[index].get().utf8ToString();
return bytesToString(values[index].get());
}

/**
* Convert the stored bytes to a String.
*/
protected String bytesToString(BytesRef bytes) {
return bytes.utf8ToString();
}

public String getValue() {
public final String getValue() {
return get(0);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
/**
* Specialization of {@link LeafNumericFieldData} for floating-point numerics.
*/
abstract class LeafDoubleFieldData implements LeafNumericFieldData {
public abstract class LeafDoubleFieldData implements LeafNumericFieldData {

private final long ramBytesUsed;

LeafDoubleFieldData(long ramBytesUsed) {
protected LeafDoubleFieldData(long ramBytesUsed) {
this.ramBytesUsed = ramBytesUsed;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@
/**
* Specialization of {@link LeafNumericFieldData} for integers.
*/
abstract class LeafLongFieldData implements LeafNumericFieldData {
public abstract class LeafLongFieldData implements LeafNumericFieldData {

private final long ramBytesUsed;
/**
* Type of this field. Used to expose appropriate types in {@link #getScriptValues()}.
*/
private final NumericType numericType;

LeafLongFieldData(long ramBytesUsed, NumericType numericType) {
protected LeafLongFieldData(long ramBytesUsed, NumericType numericType) {
this.ramBytesUsed = ramBytesUsed;
this.numericType = numericType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
import org.apache.lucene.search.IndexSortSortedNumericDocValuesRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.time.DateFormatter;
import org.elasticsearch.common.time.DateFormatters;
import org.elasticsearch.common.time.DateMathParser;
Expand All @@ -63,6 +63,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
Expand Down Expand Up @@ -343,60 +344,83 @@ public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower
DateMathParser parser = forcedDateParser == null
? dateMathParser
: forcedDateParser;
return dateRangeQuery(lowerTerm, upperTerm, includeLower, includeUpper, timeZone, parser, context, resolution, (l, u) -> {
Query query = LongPoint.newRangeQuery(name(), l, u);
if (hasDocValues()) {
Query dvQuery = SortedNumericDocValuesField.newSlowRangeQuery(name(), l, u);
query = new IndexOrDocValuesQuery(query, dvQuery);

if (context.indexSortedOnField(name())) {
query = new IndexSortSortedNumericDocValuesRangeQuery(name(), l, u, query);
}
}
return query;
});
}

public static Query dateRangeQuery(
Object lowerTerm,
Object upperTerm,
boolean includeLower,
boolean includeUpper,
@Nullable ZoneId timeZone,
DateMathParser parser,
QueryShardContext context,
Resolution resolution,
BiFunction<Long, Long, Query> builder
) {
return handleNow(context, nowSupplier -> {
long l, u;
if (lowerTerm == null) {
l = Long.MIN_VALUE;
} else {
l = parseToLong(lowerTerm, !includeLower, timeZone, parser, nowSupplier, resolution);
if (includeLower == false) {
++l;
}
}
if (upperTerm == null) {
u = Long.MAX_VALUE;
} else {
u = parseToLong(upperTerm, includeUpper, timeZone, parser, nowSupplier, resolution);
if (includeUpper == false) {
--u;
}
}
return builder.apply(l, u);
});
}

/**
* Handle {@code now} in queries.
* @param context context from which to read the current time
* @param builder build the query
* @return the result of the builder, wrapped in {@link DateRangeIncludingNowQuery} if {@code now} was used.
*/
public static Query handleNow(QueryShardContext context, Function<LongSupplier, Query> builder) {
boolean[] nowUsed = new boolean[1];
LongSupplier nowSupplier = () -> {
nowUsed[0] = true;
return context.nowInMillis();
};
long l, u;
if (lowerTerm == null) {
l = Long.MIN_VALUE;
} else {
l = parseToLong(lowerTerm, !includeLower, timeZone, parser, nowSupplier);
if (includeLower == false) {
++l;
}
}
if (upperTerm == null) {
u = Long.MAX_VALUE;
} else {
u = parseToLong(upperTerm, includeUpper, timeZone, parser, nowSupplier);
if (includeUpper == false) {
--u;
}
}

Query query = LongPoint.newRangeQuery(name(), l, u);
if (hasDocValues()) {
Query dvQuery = SortedNumericDocValuesField.newSlowRangeQuery(name(), l, u);
query = new IndexOrDocValuesQuery(query, dvQuery);

if (context.indexSortedOnField(name())) {
query = new IndexSortSortedNumericDocValuesRangeQuery(name(), l, u, query);
}
}

if (nowUsed[0]) {
query = new DateRangeIncludingNowQuery(query);
}
return query;
Query query = builder.apply(nowSupplier);
return nowUsed[0] ? new DateRangeIncludingNowQuery(query) : query;
}

public long parseToLong(Object value, boolean roundUp,
@Nullable ZoneId zone, @Nullable DateMathParser forcedDateParser, LongSupplier now) {
DateMathParser dateParser = dateMathParser();
if (forcedDateParser != null) {
dateParser = forcedDateParser;
}
public long parseToLong(Object value, boolean roundUp, @Nullable ZoneId zone, DateMathParser dateParser, LongSupplier now) {
dateParser = dateParser == null ? dateMathParser() : dateParser;
return parseToLong(value, roundUp, zone, dateParser, now, resolution);
}

String strValue;
if (value instanceof BytesRef) {
strValue = ((BytesRef) value).utf8ToString();
} else {
strValue = value.toString();
}
Instant instant = dateParser.parse(strValue, now, roundUp, zone);
return resolution.convert(instant);
public static long parseToLong(
Object value,
boolean roundUp,
@Nullable ZoneId zone,
DateMathParser dateParser,
LongSupplier now,
Resolution resolution
) {
return resolution.convert(dateParser.parse(BytesRefs.toString(value), now, roundUp, zone));
}

@Override
Expand All @@ -416,7 +440,7 @@ public Relation isFieldWithinQuery(IndexReader reader,

long fromInclusive = Long.MIN_VALUE;
if (from != null) {
fromInclusive = parseToLong(from, !includeLower, timeZone, dateParser, context::nowInMillis);
fromInclusive = parseToLong(from, !includeLower, timeZone, dateParser, context::nowInMillis, resolution);
if (includeLower == false) {
if (fromInclusive == Long.MAX_VALUE) {
return Relation.DISJOINT;
Expand All @@ -427,7 +451,7 @@ public Relation isFieldWithinQuery(IndexReader reader,

long toInclusive = Long.MAX_VALUE;
if (to != null) {
toInclusive = parseToLong(to, includeUpper, timeZone, dateParser, context::nowInMillis);
toInclusive = parseToLong(to, includeUpper, timeZone, dateParser, context::nowInMillis, resolution);
if (includeUpper == false) {
if (toInclusive == Long.MIN_VALUE) {
return Relation.DISJOINT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.similarity.SimilarityService;
import org.elasticsearch.indices.mapper.MapperRegistry;
import org.elasticsearch.script.ScriptService;

import java.util.HashMap;
import java.util.Iterator;
Expand All @@ -54,26 +55,29 @@ public class DocumentMapperParser {

private final Map<String, Mapper.TypeParser> typeParsers;
private final Map<String, MetadataFieldMapper.TypeParser> rootTypeParsers;
private final ScriptService scriptService;

public DocumentMapperParser(IndexSettings indexSettings, MapperService mapperService, NamedXContentRegistry xContentRegistry,
SimilarityService similarityService, MapperRegistry mapperRegistry, Supplier<QueryShardContext> queryShardContextSupplier) {
SimilarityService similarityService, MapperRegistry mapperRegistry,
Supplier<QueryShardContext> queryShardContextSupplier, ScriptService scriptService) {
this.mapperService = mapperService;
this.xContentRegistry = xContentRegistry;
this.similarityService = similarityService;
this.queryShardContextSupplier = queryShardContextSupplier;
this.scriptService = scriptService;
this.typeParsers = mapperRegistry.getMapperParsers();
this.indexVersionCreated = indexSettings.getIndexVersionCreated();
this.rootTypeParsers = mapperRegistry.getMetadataMapperParsers(indexVersionCreated);
}

public Mapper.TypeParser.ParserContext parserContext() {
return new Mapper.TypeParser.ParserContext(similarityService::getSimilarity, mapperService,
typeParsers::get, indexVersionCreated, queryShardContextSupplier, null);
typeParsers::get, indexVersionCreated, queryShardContextSupplier, null, scriptService);
}

public Mapper.TypeParser.ParserContext parserContext(DateFormatter dateFormatter) {
return new Mapper.TypeParser.ParserContext(similarityService::getSimilarity, mapperService,
typeParsers::get, indexVersionCreated, queryShardContextSupplier, dateFormatter);
typeParsers::get, indexVersionCreated, queryShardContextSupplier, dateFormatter, scriptService);
}

public DocumentMapper parse(@Nullable String type, CompressedXContent source) throws MapperParsingException {
Expand Down
Loading