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

Add 'flatten' parameter to object mappers #78997

Closed

Conversation

romseygeek
Copy link
Contributor

@romseygeek romseygeek commented Oct 12, 2021

Objects with flatten:true will automatically flatten all sub-objects into dot-delimited
fields, allowing users to specify field names that are dot-prefixes of other fields.

For example, say you have a set of fields metric.value, metric.value.min and
metric.value.max. Setting flatten:true on the top-level metric object will
allow value, value.min and value.max to all appear as leaf fields:

"properties" : {
  "metric" : {
    "type" : "object",
    "flatten" : true,
    "properties" : {
      "value" : { "type" : "long" },
      "value.max" : { "type" : "long" },
      "value.min" : { "type" : "long" },
    }
  }
}

Objects with flatten:true cannot contain further object mappers.

Relates to #63530

@romseygeek romseygeek added >enhancement :Search Foundations/Mapping Index mappings, including merging and defining field types v8.0.0 v7.16.0 labels Oct 12, 2021
@romseygeek romseygeek self-assigned this Oct 12, 2021
@elasticmachine elasticmachine added the Team:Search Meta label for search team label Oct 12, 2021
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-search (Team:Search)

@romseygeek romseygeek marked this pull request as draft October 12, 2021 14:11
@romseygeek
Copy link
Contributor Author

I want to let CI chew on this and I'm pretty sure there are further cleanups I can make in DocumentParser (which now has a bunch of unused code) and related tests, but it would be good to get some feedback on whether we think this is the right way of implementing this, at least as an external API.

Note that as of now I have explicitly not implemented this on nested mappers, but it would be easy enough to extend it there.

return mappingLookup.getMapping().mappingUpdate(root);
}

private static RootObjectMapper createDynamicUpdate(MappingLookup mappingLookup,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The vast bulk of this logic is now moved into the new ObjectMapper.Builder#addDynamic() method. Instead of creating concrete object mappers and recursively merging them, instead we pass each mapper to a root object builder. The builder checks to see if there are any dots in the mapper's field name, and if there are and the object is not flattened then we strip off the first object name, create the relevant object builder if it doesn't already exist, and pass the shortened name along with the mapper down to the next level. If the object is flattened, then we just add the mapper directly underneath it.

Tuple<Integer, ObjectMapper> parentMapperTuple = getDynamicParentMapper(context, paths, parentMapper);
parentMapper = parentMapperTuple.v2();
int pathLength = parentMapperTuple.v1();
StringBuilder compositeFieldName = new StringBuilder(paths[pathLength]);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This part allows us to handle deeply nested object paths that become flattened at some arbitrary point. getDynamicParentMapper will stop building intermediate object mappers if one of them is flattened, and this logic builds up the final field name from the point of the flattened object.

@Override
public String toString() {
return name() + ":" + Strings.toString(this);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not strictly related, but it made debugging this so much easier that I thought it worth leaving in.

copy.numericDetection = new Explicit<>(Defaults.NUMERIC_DETECTION, false);
//also no need to carry the already defined runtime fields, only new ones need to be added
copy.runtimeFields.clear();
return copy;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't need to set all the dynamicTemplates, etc, because we're creating a Builder which already has all these set to implicit defaults.

@romseygeek romseygeek marked this pull request as ready for review October 13, 2021 10:25
@danhermann danhermann added v8.1.0 and removed v7.16.0 labels Oct 27, 2021
@arteam arteam removed the v8.0.0 label Jan 12, 2022
@mark-vieira mark-vieira added v8.2.0 and removed v8.1.0 labels Feb 2, 2022
@elasticsearchmachine
Copy link
Collaborator

Hi @romseygeek, I've created a changelog YAML for you.

@javanna
Copy link
Member

javanna commented Apr 28, 2022

Superseded by #86166 , made possible by #79922 and #81449.

@javanna javanna closed this Apr 28, 2022
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 v8.3.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants