-
Notifications
You must be signed in to change notification settings - Fork 25k
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
RuntimeField to expose more than one MappedFieldType #73900
RuntimeField to expose more than one MappedFieldType #73900
Conversation
Up until now, there was a 1:1 relationship between a RuntimeField and a MappedFieldType. Actually, the two were only recently split to support emitting multiple fields from a single runtime script. The next step is to change the signature of asMappedFieldType to make it return multiple sub-fields. The leaf fields that are supported to-date will return a collection with a single item, but the upcoming runtime "object" field will return as many subfields as are listed in its definition. Together with this, we are introducing two consistency checks: - sub-fields exposed by a RuntimeField either have its same name, or belong to its namespace (e.g. object.subfield) - there can't be two mapped field types with the same name as part of the same runtime section, overrides happen defining the same field in two different sections (index mappings and search request)
Pinging @elastic/es-search (Team:Search) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - I left a question about subfield naming though which I think we need to address before committing.
RuntimeField runtimeField = context.root().getRuntimeField(fieldPath); | ||
if (runtimeField != null) { | ||
return new NoOpFieldMapper(subfields[subfields.length - 1], runtimeField.asMappedFieldType().name()); | ||
MappedFieldType fieldType = context.mappingLookup().getFieldType(fieldPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this work with flattened fields? I guess they should already be picked up by the parent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that flattened have a mapper that would be found above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think that flattened fields will be found earlier. Would you be up for adding a test for this, as it seems quite subtle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened #74112
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the extra test !
.collect(Collectors.toList()); | ||
if (names.isEmpty() == false) { | ||
throw new IllegalArgumentException("Found sub-fields with name not belonging to the parent field they are part of " | ||
+ names); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting, are we sure that we want to enforce this? We've discussed in the past wanting to have subfields that are aliased out to the root so that they don't appear in their parent object's namespace. If we do enforce this then that's another reason to allow runtime aliases to refer to other runtime fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was assuming that we do want to enforce this, otherwise object "foo" can emit sub-fields that don't belong to its namespace. We were trying to apply a similar assertion with the dynamic field type approach but it turned out not to be feasible due to flattened and aliases, I think.
In reality, this will not be possible if we look at how you define sub-fields (yet I think it's good to check to prevent mistakes), because the full name is generated by concatenating the name of the parent and the name of the sub-field:
"log" : {
"type" : "I don't have a name yet"
"script" : "...."
"fields" : {
"client_ip" : {
"type" : "ip"
}
}
}
Maybe I should make it an illegal state instead of a user error...
While it is possible to have users define the full path in the sub-fields, that would make the "object" name almost useless and would feel weird. Your conclusion about aliases makes sense to me, although it is very easy to make an alias runtime field with a super small script?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made this an IllegalStateException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using IllegalStateException
or an assertion here makes sense to me, as it'd indicate a bug in our code (or plugin authors' code). Not relevant to this PR, but I noticed we don't assert this for FieldMapper#iterator
... maybe we should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @javanna
Up until now, there was a 1:1 relationship between a RuntimeField and a MappedFieldType. Actually, the two were only recently split to support emitting multiple fields from a single runtime script. The next step is to change the signature of asMappedFieldType to make it return multiple sub-fields. The leaf fields that are supported to-date will return a collection with a single item, but the upcoming runtime "object" field will return as many subfields as are listed in its definition. Together with this, we are introducing two consistency checks: - sub-fields exposed by a RuntimeField either have its same name, or belong to its namespace (e.g. object.subfield) - there can't be two mapped field types with the same name as part of the same runtime section, overrides happen defining the same field in two different sections (index mappings and search request)
Up until now, there was a 1:1 relationship between a RuntimeField and a MappedFieldType. Actually, the two were only recently split to support emitting multiple fields from a single runtime script. The next step is to change the signature of asMappedFieldType to make it return multiple sub-fields. The leaf fields that are supported to-date will return a collection with a single item, but the upcoming runtime "object" field will return as many subfields as are listed in its definition. Together with this, we are introducing two consistency checks: - sub-fields exposed by a RuntimeField either have its same name, or belong to its namespace (e.g. object.subfield) - there can't be two mapped field types with the same name as part of the same runtime section, overrides happen defining the same field in two different sections (index mappings and search request)
RuntimeField runtimeField = context.root().getRuntimeField(fieldPath); | ||
if (runtimeField != null) { | ||
return new NoOpFieldMapper(subfields[subfields.length - 1], runtimeField.asMappedFieldType().name()); | ||
MappedFieldType fieldType = context.mappingLookup().getFieldType(fieldPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think that flattened fields will be found earlier. Would you be up for adding a test for this, as it seems quite subtle?
.collect(Collectors.toList()); | ||
if (names.isEmpty() == false) { | ||
throw new IllegalArgumentException("Found sub-fields with name not belonging to the parent field they are part of " | ||
+ names); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using IllegalStateException
or an assertion here makes sense to me, as it'd indicate a bug in our code (or plugin authors' code). Not relevant to this PR, but I noticed we don't assert this for FieldMapper#iterator
... maybe we should.
Sorry for the late review, I had it open for a long time without refreshing the page! |
Up until now, there was a 1:1 relationship between a RuntimeField and a MappedFieldType. Actually, the two were only recently split to support emitting multiple fields from a single runtime script. The next step is to change the signature of asMappedFieldType to make it return multiple sub-fields. The leaf fields that are supported to-date will return a collection with a single item, but the upcoming runtime "object" field will return as many subfields as are listed in its definition.
Together with this, we are introducing two consistency checks: