-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
Allow ObjectParsers to specify required sets of fields #49661
Allow ObjectParsers to specify required sets of fields #49661
Conversation
ConstructingObjectParser can be used to specify required fields, but it is still difficult to configure "sets" of fields where only one of the set is required (requiring hand-rolled logic in each ConstructingObjectParser, or adding special validation methods to objects that are called after building the object). This commit adds a new method on ObjectParser which allows the parsers to register required sets. E.g. ["foo", "bar"] can be registered, which means "foo", "bar" or both must be configured by the user otherwise an exception is thrown. This pattern crops up in many places in our parsers, but as a demonstration this PR adds validation for aggregation "field" and "script" fields. One or both must be configured on all aggregations, omitting both should result in an exception. This was previously handled far downstream resulting in an aggregation exception, when it should be a parse exception.
Pinging @elastic/es-core-infra (:Core/Infra/Core) |
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.
Overall having better control over what combinations of fields are allowed or must be present, but I wonder if this is sufficient. The examples given in javadoc are pretty simplistic, and shown like a query, while we are talking about json objects. Would it be possible to give closer to a real world example?
String[] requriedFields = iter.next(); | ||
for (String field : requriedFields) { | ||
if (field.equals(currentFieldName)) { | ||
iter.remove(); |
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.
Isn't this removing the value from the ObjectParser's instance, which is static?
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.
Oof, you're right. I was just looking at the class itself (which is not static) but everyone declares ObjectParser as static. I'll fiddle to get rid of the mutability
server/src/test/java/org/elasticsearch/search/aggregations/AggregatorFactoriesBuilderTests.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
Thanks!
The motivating example for me was from aggregations: Regarding the agg-specific parts of the PR, I can remove them if we want it to be just infrastructure, and followup with a second PR for the agg stuff. |
I backed out all the agg-related changes (making Fixed access to the static object by making a copy of the list before parsing. This didn't feel especially clever, so open to alternatives :) Also beefed up the javadocs a bit with json examples |
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.
A few more comments.
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/test/java/org/elasticsearch/common/xcontent/ObjectParserTests.java
Outdated
Show resolved
Hide resolved
Review comments addressed! The extra javadoc markup made the json snippets significantly less readable though so not sure if they are still helpful or not... I opted to ignore EDIT Looks like javadoc is unhappy, fixing... EDIT 2 Hmm, so it seems that
But the build fails when a "summary" field is included
|
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
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
libs/x-content/src/main/java/org/elasticsearch/common/xcontent/AbstractObjectParser.java
Outdated
Show resolved
Hide resolved
Had a chance to revisit this, think I resolved the javadoc compilation build issue. Unsure why the "summary" field broke everything, but replacing it with a This got stale, merged in master and fixed conflicts, will monitor to make sure there aren't any new test issues before merging. |
@elasticmachine update branch |
ConstructingObjectParser can be used to specify required fields, but it is still difficult to configure "sets" of fields where only one of the set is required (requiring hand-rolled logic in each ConstructingObjectParser, or adding special validation methods to objects that are called after building the object). This commit adds a new method on ObjectParser which allows the parsers to register required sets. E.g. ["foo", "bar"] can be registered, which means "foo", "bar" or both must be configured by the user otherwise an exception is thrown. This pattern crops up in many places in our parsers; a good example are the aggregation "field" and "script" fields. One or both must be configured on all aggregations, omitting both should result in an exception. This was previously handled far downstream resulting in an aggregation exception, when it should be a parse exception.
ConstructingObjectParser
can be used to specify required fields, but it is still difficult to configure "sets" of fields where only one of the set is required ((foo OR bar) AND (bizz OR buzz)
). It requires hand-rolled logic in eachConstructingObjectParser
, or special validation methods that are called during/after object construction.This commit adds a new method on
ObjectParser
which allows the parsers to register required sets. E.g.["foo", "bar"]
can be registered, which means "foo", "bar" or both must be configured by the user otherwise an exception is thrown.This pattern crops up in many places in our parsers, but as a demonstration this PR adds validation for aggregation
"field"
and"script"
fields. One or both must be configured on all aggregations, and omitting both should result in an exception. This was previously handled far downstream resulting in an aggregation exception, when it should be a parse exception.This might be a controversial change given it's partial overlap with
ConstructingObjectParser
. Open to changes/suggestions, as well as better naming :)Closes #48824