Skip to content
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

Merged
merged 29 commits into from
Dec 8, 2020

Conversation

javanna
Copy link
Member

@javanna javanna commented Nov 25, 2020

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.
@javanna javanna added >enhancement :Search Foundations/Mapping Index mappings, including merging and defining field types v8.0.0 v7.11.0 labels Nov 25, 2020
builder = new BinaryFieldMapper.Builder(currentFieldName);
}
return builder;
return dynamicFieldsBuilder.newDynamicBinaryField(context, currentFieldName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat!

throw new IllegalStateException("Can't handle serializing a dynamic type with content token [" + token + "] and field name ["
+ currentFieldName + "]");
}

Copy link
Member Author

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);
Copy link
Member Author

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.

Copy link
Member

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?

Copy link
Member Author

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);
}
Copy link
Member Author

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?

Copy link
Member

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.....

@javanna javanna marked this pull request as ready for review December 7, 2020 21:08
@javanna
Copy link
Member Author

javanna commented Dec 8, 2020

I am wondering whether I should update the qa tests as part of this PR or as a follow-up.

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.

Copy link
Contributor

@romseygeek romseygeek left a 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);
}
Copy link
Contributor

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.

Copy link
Member Author

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\"}}}}}}",
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Member Author

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);
Copy link
Contributor

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?

Copy link
Member Author

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.

@javanna
Copy link
Member Author

javanna commented Dec 8, 2020

run elasticsearch-ci/packaging-sample-unix

@javanna javanna merged commit e144471 into elastic:master Dec 8, 2020
javanna added a commit to javanna/elasticsearch that referenced this pull request Dec 8, 2020
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.
javanna added a commit that referenced this pull request Dec 8, 2020
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.
@jtibshirani
Copy link
Contributor

I was catching up on this exciting change and noticed -- should we update the docs for the dynamic param?

@javanna
Copy link
Member Author

javanna commented Dec 10, 2020

@jtibshirani yes I was waiting for #62653 to be merged so we can go ahead and document dynamic:runtime too.

@lockewritesdocs
Copy link
Contributor

@jtibshirani, I opened #66194 to include changes for dynamic runtime settings, which affects the dynamic parameter page (and a few others).

javanna added a commit to javanna/elasticsearch that referenced this pull request Jun 17, 2021
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.
javanna added a commit that referenced this pull request Jun 18, 2021
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
javanna added a commit to javanna/elasticsearch that referenced this pull request Jun 18, 2021
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
javanna added a commit that referenced this pull request Jun 18, 2021
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>enhancement :Search Foundations/Mapping Index mappings, including merging and defining field types Team:Search Meta label for search team v7.11.0 v8.0.0-alpha1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants