-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Finalize fields in postaggs #2883
Conversation
Thanks @jaehc, we'll try to get to reviewing this soon. We are really backlogged on PRs right now. |
rebased to master |
@@ -84,6 +85,7 @@ public AggregatorsModule() | |||
@JsonSubTypes(value = { | |||
@JsonSubTypes.Type(name = "arithmetic", value = ArithmeticPostAggregator.class), | |||
@JsonSubTypes.Type(name = "fieldAccess", value = FieldAccessPostAggregator.class), | |||
@JsonSubTypes.Type(name = "finalFieldAccess", value = FinalFieldAccessPostAggregator.class), |
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.
can we call this FinalizingFieldAccessPostAggregator?
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 will handle 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.
done
@nishantmonu51 can you help with review here? |
@@ -55,6 +61,18 @@ public static void verifyAggregations( | |||
"Missing fields [%s] for postAggregator [%s]", missing, postAgg.getName() | |||
); | |||
Preconditions.checkArgument(combinedAggNames.add(postAgg.getName()), "[%s] already defined", postAgg.getName()); | |||
|
|||
if (postAgg instanceof HasDependentAggFactories) { |
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 probably will not work when a dependent post agg is used within Arithmetic post aggregator.
We need to have a better way to inject aggregators instead of using instanceOf.
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 Ut for a finalizing post aggregator with arithmetic post aggregator has beed added. It seems work, but do you mean this case or other situation? Of course, I agree that we can use better ways to get aggregators injected if some. Would you give me some recommandation for this?
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 believe you are referring to testComputedInArithmeticPostAggregator.
there its only testing computation instead of dependency injection.
can you add/modify the test to call Queries.prepareAggregations() for arithmetic aggregator and verify that all dependencies are set properly ?
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.
@nishantmonu51 You're right. Injections of post aggs in Arithmetic post aggregator does not work because jackson injects the post aggs while creating an instance which means there is no chance to go through Queries.prepareAggregations()
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.
@nishantmonu51 I've made ArithmeticPostAggregator
implements HasDependentAggFactories
and modify a existing Ut for that(testIngestAndQueryWithArithmeticPostAggregator
). It seems work so far now. But, do you think things are getting ugly?
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.
yeah, looking at this further, there seems to be other aggregators too which act as a wrapper for other postAggs e.g DoubleGreatestPostAggregator, LongGreatestPostAggregator etc.
To make it more cleaner, I think it might just be simpler to add new method setDependentAggFactories in interface PostAggregator itself. Any implementation not having any dependent post aggregator will have a no-op implementation.
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.
@nishantmonu51 It makes sense to me, I will add setDependentAggFactories
in PostAggregator
and maybe I guess we would probably need another contextual information later and think about it then.
@jaehc: can you address #2883 (comment) ? |
ping @jaehc |
@fjy @nishantmonu51 sorry for being late. I will handle it |
@nishantmonu51 |
LGTM, with the changes for decorate. @fjy Can you also review ? |
updated the master comment to change finalFieldAccess -> finalizingFieldAccess |
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.
👍
Incompatibilities need called out in the master comment, please |
@nishantmonu51 Thanks for giving a review. Is there somethign I need to handle about this PR? By the way, what is |
@jaehc master comment is the top comment in the issue at #2883 (comment) |
Taking a look. |
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.
@jaehc thanks for the contribution. I just had some small comments and a request to add Comparator support too.
@@ -35,4 +35,6 @@ | |||
public Object compute(Map<String, Object> combinedAggregators); | |||
|
|||
public String getName(); | |||
|
|||
public PostAggregator decorate(Map<String, AggregatorFactory> aggregators); |
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.
Could you please add a javadoc to this explaining what it's supposed to do, and what aggregators
is expected to contain? It's not clear from the method type signature how this would work.
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.
You're right. It needs more explanation. I put some comments on it.
@Override | ||
public FinalizingFieldAccessPostAggregator decorate(final Map<String, AggregatorFactory> aggregators) | ||
{ | ||
return new FinalizingFieldAccessPostAggregator(name, fieldName) { |
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 should override getComparator too, so the post-aggregator can be sorted on. This should be possible by using the comparator of aggregators.get(fieldName).getComparator()
if that exists, and Ordering.natural().nullsFirst()
otherwise (hoping for the best).
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.
That sound good to me. But, why do we use Ordering.natural().nullsFirst()
other than only Ordering.natural()
?
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.
Just in case there's a null return value from a postaggregator, I guess.
public String toString() | ||
{ | ||
return "FinalizingFieldAccessPostAggregator{" + | ||
"name'" + 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.
name='
is missing the equals sign
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.
done
return result; | ||
} | ||
|
||
public static FinalizingFieldAccessPostAggregator buildDecorated(String 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.
@VisibleForTesting
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.
done
@@ -120,12 +120,15 @@ public GroupByQuery( | |||
Preconditions.checkArgument(spec != null, "dimensions has null DimensionSpec"); | |||
} | |||
this.aggregatorSpecs = aggregatorSpecs == null ? ImmutableList.<AggregatorFactory>of() : aggregatorSpecs; | |||
this.postAggregatorSpecs = postAggregatorSpecs == null ? ImmutableList.<PostAggregator>of() : postAggregatorSpecs; | |||
this.postAggregatorSpecs = Queries.prepareAggregations( |
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.
Seems like postAggregatorSpecs == null ? ImmutableList.<PostAggregator>of() : postAggregatorSpecs
is a common pattern, might as well have Queries.prepareAggregations
do this.
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.
Is there somewhere to apply it other than the line number of 125?
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 meant, Queries.prepareAggregations could do this… return an empty list if postAggregatorSpecs is null. This is minor thing and not really necessary though.
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class FinalizingFieldAccessPostAggregatorTest |
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.
Please add a test for the comparator too.
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.
done with testComparatorsWithFinalizing
and the below Ut.
import java.util.Set; | ||
|
||
/** | ||
*/ | ||
public class Queries | ||
{ | ||
public static void verifyAggregations( | ||
public static List<PostAggregator> decorate(List<PostAggregator> postAggs, |
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.
minor: name this decoratePostAggregators
? Or move to PostAggregators.decorate
? The name "Queries.decorate" sounds a little too generic for what this does.
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.
That sound good to me. It was somewhat obscure. For now, I rather lean to rename it. But, when we find out another things doing stuff with post aggregators, it would be good to be in a separated class like PostAggregators.decorate()
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 patch to address comments.
@@ -120,12 +120,15 @@ public GroupByQuery( | |||
Preconditions.checkArgument(spec != null, "dimensions has null DimensionSpec"); | |||
} | |||
this.aggregatorSpecs = aggregatorSpecs == null ? ImmutableList.<AggregatorFactory>of() : aggregatorSpecs; | |||
this.postAggregatorSpecs = postAggregatorSpecs == null ? ImmutableList.<PostAggregator>of() : postAggregatorSpecs; | |||
this.postAggregatorSpecs = Queries.prepareAggregations( |
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.
Is there somewhere to apply it other than the line number of 125?
public String toString() | ||
{ | ||
return "FinalizingFieldAccessPostAggregator{" + | ||
"name'" + 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.
done
return result; | ||
} | ||
|
||
public static FinalizingFieldAccessPostAggregator buildDecorated(String 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.
done
import java.util.Set; | ||
|
||
/** | ||
*/ | ||
public class Queries | ||
{ | ||
public static void verifyAggregations( | ||
public static List<PostAggregator> decorate(List<PostAggregator> postAggs, |
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.
That sound good to me. It was somewhat obscure. For now, I rather lean to rename it. But, when we find out another things doing stuff with post aggregators, it would be good to be in a separated class like PostAggregators.decorate()
@@ -35,4 +35,6 @@ | |||
public Object compute(Map<String, Object> combinedAggregators); | |||
|
|||
public String getName(); | |||
|
|||
public PostAggregator decorate(Map<String, AggregatorFactory> aggregators); |
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.
You're right. It needs more explanation. I put some comments on it.
@Override | ||
public FinalizingFieldAccessPostAggregator decorate(final Map<String, AggregatorFactory> aggregators) | ||
{ | ||
return new FinalizingFieldAccessPostAggregator(name, fieldName) { |
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.
That sound good to me. But, why do we use Ordering.natural().nullsFirst()
other than only Ordering.natural()
?
1. Implements getComparator in FinalizingFieldAccessPostAggregator and add Uts for it 2. Some minor changes like renaming a method name.
@jaehc thanks, re-reviewing. |
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 will take a look at resolving conflicts for this patch for 0.10.0. |
Opened #3957 with conflicts fixed, otherwise unchanged. |
According to #2433, automatically finalizing aggregators in a post aggregator sounds really good to druid client programs.
I gave it a try to make it work and it seems good. Now, you can write a query like the below. However, there are some duplicate code blocks here and there. Any comments on refactoring would be welcomed.
instead of
This change is![Reviewable](https://camo.githubusercontent.com/1541c4039185914e83657d3683ec25920c672c6c5c7ab4240ee7bff601adec0b/68747470733a2f2f72657669657761626c652e696f2f7265766965775f627574746f6e2e737667)