-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Introduce dynamic runtime setting #65489
Introduce dynamic runtime setting #65489
Conversation
The dynamic:runtime setting is similar to dynamic:true in that it dynamically defines fields based on values parsed from incoming documents. Though instead of defining leaf fields under properties, it defines them as runtime fields under the runtime section. This is useful in scenarios where search speed can be traded for storage costs, given that runtime fields are loaded at runtime rather than indexed.
server/src/main/java/org/elasticsearch/index/mapper/DynamicFieldsBuilder.java
Outdated
Show resolved
Hide resolved
server/src/main/java/org/elasticsearch/index/mapper/DynamicRuntimeFieldsBuilder.java
Show resolved
Hide resolved
server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java
Outdated
Show resolved
Hide resolved
builder = new BinaryFieldMapper.Builder(currentFieldName); | ||
} | ||
return builder; | ||
return dynamicFieldsBuilder.newDynamicBinaryField(context, currentFieldName); |
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.
Neat!
server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java
Outdated
Show resolved
Hide resolved
throw new IllegalStateException("Can't handle serializing a dynamic type with content token [" + token + "] and field name [" | ||
+ currentFieldName + "]"); | ||
} | ||
|
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 all moved to DynamicFieldsBuilder now. it simplifies things as we no longer need to return either a runtime field or a mapper builder. We can directly do what's necessary, meaning adding the field where appropriate to the context, and potentially going further with parsing for concrete fields.
if (dynamicMappers.isEmpty() == false) { | ||
root = createDynamicUpdate(mapping.root, docMapper, dynamicMappers); | ||
} else { | ||
root = (RootObjectMapper)mapping.root.mappingUpdate(null); |
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 pretty horrible. I am not sure how to make it better yet. We are introducing one reason to update the root without having to add a mapper to it.
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.
Passing null
to make a copy is a bit sad, yeah. Maybe we could have a copy
method?
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 followed this approach and things do look a bit better, thanks!
@@ -407,6 +432,9 @@ public void seqID(SeqNoFieldMapper.SequenceIDFields seqID) { | |||
|
|||
@Override | |||
public void addDynamicMapper(Mapper mapper) { | |||
if (mapper instanceof ObjectMapper) { | |||
dynamicObjectMappers.put(mapper.name(), (ObjectMapper)mapper); | |||
} |
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 not particularly elegant, but it does the job. Ideas on how to make it nicer?
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.
Not really.... We do a fair bit of `instanceof to dig up ObjectMapper and its friends like MetaDataFieldMapper. It ain't great but its what we do a fair bit.....
I figured that we are not ready yet to re-enable the qa tests for runtime fields defined in index mappings, as we also need to be able to define runtime fields as part of dynamic templates, which I will work on as a follow-up. |
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 overall. I think we need to some work on DocumentParser as a whole and how it builds dynamic mappings but we can get this in first.
} | ||
root.addRuntimeFields(dynamicRuntimeFields); | ||
return mapping.mappingUpdate(root); | ||
} |
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 we should rework this to use ObjectMapper.Builder so that we can make the actual mappings immutable, but let's do that in a followup.
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.
agreed, this improvement is already listed here: #64663
assertNull(doc.rootDoc().getField("foo.bar.baz")); | ||
assertEquals("{\"_doc\":{\"dynamic\":\"false\"," + | ||
"\"runtime\":{\"foo.bar.baz\":{\"type\":\"string\"},\"foo.baz\":{\"type\":\"string\"}}," + | ||
"\"properties\":{\"foo\":{\"dynamic\":\"runtime\",\"properties\":{\"bar\":{\"type\":\"object\"}}}}}}", |
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.
Are we happy that this intermediate object with no concrete leaf fields gets added? It feels a bit weird to me, but I can see how it ends up being necessary because of all the book-keeping we do while we create dynamic mappings during parsing.
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.
good question: I have wondered the same, and wondered also: what do we do when a document is sent which contains no leaf fields, only objects? Effectively no lucene fields (besides metadata fields) are created, yet we map the objects. I followed the same pattern here, which kind of fits in the runtime section design, as it is applied on top of mappings, hence it is natural that it does not hold objects, and that only the leaf fields get mapped in there. As a consequence, unseen objects get dynamically mapped under properties in dynamic runtime mode. I can see how this may feel weird at first glance, though I wonder what the alternatives are, and what the downsides could be of this approach.
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.
replying to myself 6 months later: this would be the main downside of dynamically mapping objects under dynamic:runtime
: #70268 . I am thinking now that it makes more sense to skip mapping objects in dynamic runtime mode.
|
||
@Override | ||
public RuntimeFieldType newDynamicDateField(String name, DateFormatter dateFormatter) { | ||
return new DateScriptFieldType(name); |
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.
Shouldn't this take the date formatter into account?
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.
good point, maybe. That brings up that we may need more testing with the real implementations.
run elasticsearch-ci/packaging-sample-unix |
The dynamic:runtime setting is similar to dynamic:true in that it dynamically defines fields based on values parsed from incoming documents. Though instead of defining leaf fields under properties, it defines them as runtime fields under the runtime section. This is useful in scenarios where search speed can be traded for storage costs, given that runtime fields are loaded at runtime rather than indexed.
The dynamic:runtime setting is similar to dynamic:true in that it dynamically defines fields based on values parsed from incoming documents. Though instead of defining leaf fields under properties, it defines them as runtime fields under the runtime section. This is useful in scenarios where search speed can be traded for storage costs, given that runtime fields are loaded at runtime rather than indexed.
I was catching up on this exciting change and noticed -- should we update the docs for the |
@jtibshirani yes I was waiting for #62653 to be merged so we can go ahead and document dynamic:runtime too. |
@jtibshirani, I opened #66194 to include changes for dynamic runtime settings, which affects the |
When we introduced dynamic:runtime (elastic#65489) we decided to have it create objects dynamically under properties, as the runtime section did not (and still does not) support object fields. That proved to be a poor choice, because the runtime section is flat, supports dots in field names, and does not really need objects. Also, these end up causing unnecessary mapping conflicts. With this commit we adapt dynamic:runtime to not dynamically create objects.
When we introduced dynamic:runtime (#65489) we decided to have it create objects dynamically under properties, as the runtime section did not (and still does not) support object fields. That proved to be a poor choice, because the runtime section is flat, supports dots in field names, and does not really need objects. Also, these end up causing unnecessary mapping conflicts. With this commit we adapt dynamic:runtime to not dynamically create objects. Closes #70268
When we introduced dynamic:runtime (elastic#65489) we decided to have it create objects dynamically under properties, as the runtime section did not (and still does not) support object fields. That proved to be a poor choice, because the runtime section is flat, supports dots in field names, and does not really need objects. Also, these end up causing unnecessary mapping conflicts. With this commit we adapt dynamic:runtime to not dynamically create objects. Closes elastic#70268
When we introduced dynamic:runtime (#65489) we decided to have it create objects dynamically under properties, as the runtime section did not (and still does not) support object fields. That proved to be a poor choice, because the runtime section is flat, supports dots in field names, and does not really need objects. Also, these end up causing unnecessary mapping conflicts. With this commit we adapt dynamic:runtime to not dynamically create objects. Closes #70268
The dynamic:runtime setting is similar to dynamic:true in that it dynamically defines fields based on values parsed from incoming documents. Though instead of defining leaf fields under properties, it defines them as runtime fields under the runtime section. This is useful in scenarios where search speed can be traded for storage costs, given that runtime fields are loaded at runtime rather than indexed.