-
Notifications
You must be signed in to change notification settings - Fork 25.8k
Add aliases as runtime fields #70065
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
Changes from 1 commit
83d921d
74b4349
cdeb51a
b9e8e3a
33dbf9c
c7c0db4
c49ed9c
88bed88
fdd27a4
9cbee43
3389a2d
175f442
9151775
94fc104
683d1be
0b4ca87
38ce282
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
| * in compliance with, at your election, the Elastic License 2.0 or the Server | ||
| * Side Public License, v 1. | ||
| */ | ||
|
|
||
| package org.elasticsearch.index.mapper; | ||
|
|
||
| import org.elasticsearch.common.xcontent.XContentBuilder; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.List; | ||
| import java.util.function.Function; | ||
|
|
||
| public class AliasRuntimeField implements RuntimeFieldType { | ||
|
|
||
| public static final String CONTENT_TYPE = "alias"; | ||
|
|
||
| private static class Builder extends RuntimeFieldType.Builder { | ||
|
|
||
| final FieldMapper.Parameter<String> path = FieldMapper.Parameter.stringParam( | ||
| "path", | ||
| true, | ||
| RuntimeFieldType.initializerNotSupported(), | ||
| null | ||
| ).setValidator( | ||
| s -> { | ||
| if (s == null) { | ||
| throw new MapperParsingException("Missing required parameter [path]"); | ||
| } | ||
| } | ||
| ); | ||
|
|
||
| protected Builder(String name) { | ||
| super(name); | ||
| } | ||
|
|
||
| @Override | ||
| protected List<FieldMapper.Parameter<?>> getParameters() { | ||
| return List.of(path); | ||
| } | ||
|
|
||
| @Override | ||
| protected RuntimeFieldType buildFieldType() { | ||
| return new AliasRuntimeField(name, path.get()); | ||
| } | ||
| } | ||
|
|
||
| public static final RuntimeFieldType.Parser PARSER = new RuntimeFieldType.Parser((n, c) -> new Builder(n)); | ||
|
|
||
| private final String name; | ||
| private final String path; | ||
|
|
||
| public AliasRuntimeField(String name, String path) { | ||
| this.name = name; | ||
| this.path = path; | ||
| } | ||
|
|
||
| @Override | ||
| public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
| builder.startObject(name); | ||
| builder.field("type", "alias"); | ||
| builder.field("path", path); | ||
| builder.endObject(); | ||
| return builder; | ||
| } | ||
|
|
||
| @Override | ||
| public MappedFieldType asMappedFieldType(Function<String, MappedFieldType> lookup) { | ||
javanna marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| MappedFieldType ft = lookup.apply(path); | ||
| if (ft == null) { | ||
| throw new IllegalStateException("Cannot resolve alias [" + name + "]: path [" + path + "] does not exist"); | ||
|
||
| } | ||
| return ft; | ||
| } | ||
|
|
||
| @Override | ||
| public String name() { | ||
| return name; | ||
| } | ||
|
|
||
| @Override | ||
| public String typeName() { | ||
| return CONTENT_TYPE; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| import java.util.LinkedHashSet; | ||
| import java.util.Map; | ||
| import java.util.Set; | ||
| import java.util.function.Predicate; | ||
|
|
@@ -24,6 +25,7 @@ | |
| */ | ||
| final class FieldTypeLookup { | ||
| private final Map<String, MappedFieldType> fullNameToFieldType = new HashMap<>(); | ||
| private final Map<String, RuntimeFieldType> runtimeFields = new HashMap<>(); | ||
|
|
||
| /** | ||
| * A map from field name to all fields whose content has been copied into it | ||
|
|
@@ -71,7 +73,7 @@ final class FieldTypeLookup { | |
|
|
||
| for (RuntimeFieldType runtimeFieldType : runtimeFieldTypes) { | ||
| //this will override concrete fields with runtime fields that have the same name | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did you remove this comment on purpose? |
||
| fullNameToFieldType.put(runtimeFieldType.name(), runtimeFieldType); | ||
| runtimeFields.put(runtimeFieldType.name(), runtimeFieldType); | ||
| } | ||
|
|
||
| this.dynamicKeyLookup = new DynamicKeyFieldTypeLookup(dynamicKeyMappers, aliasToConcreteName); | ||
|
|
@@ -81,6 +83,33 @@ final class FieldTypeLookup { | |
| * Returns the mapped field type for the given field name. | ||
| */ | ||
| MappedFieldType get(String field) { | ||
| GuardedFieldTypeLookup guardedLookup = new GuardedFieldTypeLookup(); | ||
| return guardedLookup.get(field); | ||
| } | ||
|
|
||
| private class GuardedFieldTypeLookup { | ||
|
||
|
|
||
| Set<String> fieldPath = new LinkedHashSet<>(); | ||
|
|
||
| MappedFieldType get(String field) { | ||
| if (fieldPath.contains(field)) { | ||
| throw new IllegalStateException("Loop in field resolution detected: " + String.join("->", fieldPath) + "->" + field); | ||
| } | ||
| fieldPath.add(field); | ||
| RuntimeFieldType runtimeFieldType = FieldTypeLookup.this.runtimeFields.get(field); | ||
| if (runtimeFieldType != null) { | ||
| return runtimeFieldType.asMappedFieldType(this::get); | ||
| } | ||
| return getConcrete(field); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns the mapped field type for the given field, excluding runtime fields | ||
| * @param field the field name | ||
| * @return a mapped field type, or null if the field does not exist | ||
| */ | ||
| MappedFieldType getConcrete(String field) { | ||
romseygeek marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| MappedFieldType fieldType = fullNameToFieldType.get(field); | ||
| if (fieldType != null) { | ||
| return fieldType; | ||
|
|
@@ -100,6 +129,11 @@ Set<String> simpleMatchToFullName(String pattern) { | |
| return Collections.singleton(pattern); | ||
| } | ||
| Set<String> fields = new HashSet<>(); | ||
| for (String field : runtimeFields.keySet()) { | ||
| if (Regex.simpleMatch(pattern, field)) { | ||
| fields.add(field); | ||
| } | ||
| } | ||
| for (String field : fullNameToFieldType.keySet()) { | ||
| if (Regex.simpleMatch(pattern, field)) { | ||
| fields.add(field); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.