From 14e33428f0f29302f0a67d05666898b6503e2457 Mon Sep 17 00:00:00 2001 From: Eyal Yurman Date: Thu, 24 Oct 2019 18:37:24 -0500 Subject: [PATCH] Moving Average extention: Add Sum averagers (#8511) * Add sum averagers. * avoid casting double to long. --- .../moving-average-query.md | 3 + .../averagers/AveragerFactory.java | 2 + .../averagers/DoubleSumAverager.java | 45 +++++++++++++++ .../averagers/DoubleSumAveragerFactory.java | 44 ++++++++++++++ .../averagers/LongSumAverager.java | 45 +++++++++++++++ .../averagers/LongSumAveragerFactory.java | 44 ++++++++++++++ .../DoubleSumAveragerFactoryTest.java | 36 ++++++++++++ .../averagers/DoubleSumAveragerTest.java | 57 +++++++++++++++++++ .../averagers/LongSumAveragerFactoryTest.java | 36 ++++++++++++ .../averagers/LongSumAveragerTest.java | 54 ++++++++++++++++++ 10 files changed, 366 insertions(+) create mode 100644 extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAverager.java create mode 100644 extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactory.java create mode 100644 extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAverager.java create mode 100644 extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactory.java create mode 100644 extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactoryTest.java create mode 100644 extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerTest.java create mode 100644 extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactoryTest.java create mode 100644 extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerTest.java diff --git a/docs/development/extensions-contrib/moving-average-query.md b/docs/development/extensions-contrib/moving-average-query.md index 8ab60cadc38..af8d902743c 100644 --- a/docs/development/extensions-contrib/moving-average-query.md +++ b/docs/development/extensions-contrib/moving-average-query.md @@ -100,10 +100,12 @@ These are properties which are common to all Averagers: * [Standard averagers](#standard-averagers): * doubleMean * doubleMeanNoNulls + * doubleSum * doubleMax * doubleMin * longMean * longMeanNoNulls + * longSum * longMax * longMin @@ -113,6 +115,7 @@ These averagers offer four functions: * Mean (Average) * MeanNoNulls (Ignores empty buckets). +* Sum * Max * Min diff --git a/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/AveragerFactory.java b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/AveragerFactory.java index a3c82781b23..f605fb51606 100644 --- a/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/AveragerFactory.java +++ b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/AveragerFactory.java @@ -36,10 +36,12 @@ import java.util.List; @JsonSubTypes.Type(name = "constant", value = ConstantAveragerFactory.class), @JsonSubTypes.Type(name = "doubleMean", value = DoubleMeanAveragerFactory.class), @JsonSubTypes.Type(name = "doubleMeanNoNulls", value = DoubleMeanNoNullAveragerFactory.class), + @JsonSubTypes.Type(name = "doubleSum", value = DoubleSumAveragerFactory.class), @JsonSubTypes.Type(name = "doubleMax", value = DoubleMaxAveragerFactory.class), @JsonSubTypes.Type(name = "doubleMin", value = DoubleMinAveragerFactory.class), @JsonSubTypes.Type(name = "longMean", value = LongMeanAveragerFactory.class), @JsonSubTypes.Type(name = "longMeanNoNulls", value = LongMeanNoNullAveragerFactory.class), + @JsonSubTypes.Type(name = "longSum", value = LongSumAveragerFactory.class), @JsonSubTypes.Type(name = "longMax", value = LongMaxAveragerFactory.class), @JsonSubTypes.Type(name = "longMin", value = LongMinAveragerFactory.class) }) diff --git a/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAverager.java b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAverager.java new file mode 100644 index 00000000000..87523f40052 --- /dev/null +++ b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAverager.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +public class DoubleSumAverager extends BaseAverager +{ + public DoubleSumAverager(int numBuckets, String name, String fieldName, int cycleSize) + { + super(Number.class, numBuckets, name, fieldName, cycleSize); + } + + @Override + protected Double computeResult() + { + double result = 0.0; + + for (int i = 0; i < numBuckets; i += cycleSize) { + if (buckets[(i + startFrom) % numBuckets] != null) { + result += (buckets[(i + startFrom) % numBuckets]).doubleValue(); + } else { + result += 0.0; + } + } + + startFrom++; + return result; + } +} diff --git a/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactory.java b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactory.java new file mode 100644 index 00000000000..f26b2ab0011 --- /dev/null +++ b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactory.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DoubleSumAveragerFactory extends ComparableAveragerFactory +{ + + @JsonCreator + public DoubleSumAveragerFactory( + @JsonProperty("name") String name, + @JsonProperty("buckets") int numBuckets, + @JsonProperty("cycleSize") Integer cycleSize, + @JsonProperty("fieldName") String fieldName + ) + { + super(name, numBuckets, fieldName, cycleSize); + } + + @Override + public Averager createAverager() + { + return new DoubleSumAverager(numBuckets, name, fieldName, cycleSize); + } +} diff --git a/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAverager.java b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAverager.java new file mode 100644 index 00000000000..c4baf84f617 --- /dev/null +++ b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAverager.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +public class LongSumAverager extends BaseAverager +{ + public LongSumAverager(int numBuckets, String name, String fieldName, int cycleSize) + { + super(Number.class, numBuckets, name, fieldName, cycleSize); + } + + @Override + protected Long computeResult() + { + long result = 0; + + for (int i = 0; i < numBuckets; i += cycleSize) { + if (buckets[(i + startFrom) % numBuckets] != null) { + result += (buckets[(i + startFrom) % numBuckets]).longValue(); + } else { + result += 0; + } + } + + startFrom++; + return result; + } +} diff --git a/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactory.java b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactory.java new file mode 100644 index 00000000000..0a603fe9c9f --- /dev/null +++ b/extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactory.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class LongSumAveragerFactory extends ComparableAveragerFactory +{ + + @JsonCreator + public LongSumAveragerFactory( + @JsonProperty("name") String name, + @JsonProperty("buckets") int numBuckets, + @JsonProperty("cycleSize") Integer cycleSize, + @JsonProperty("fieldName") String fieldName + ) + { + super(name, numBuckets, fieldName, cycleSize); + } + + @Override + public Averager createAverager() + { + return new LongSumAverager(numBuckets, name, fieldName, cycleSize); + } +} diff --git a/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactoryTest.java b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactoryTest.java new file mode 100644 index 00000000000..bb65e963afa --- /dev/null +++ b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerFactoryTest.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +import org.hamcrest.core.IsInstanceOf; +import org.junit.Assert; +import org.junit.Test; + +public class DoubleSumAveragerFactoryTest +{ + + @Test + public void testCreateAverager() + { + AveragerFactory fac = new DoubleSumAveragerFactory("test", 5, 1, "field"); + Assert.assertThat(fac.createAverager(), IsInstanceOf.instanceOf(DoubleSumAverager.class)); + } + +} diff --git a/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerTest.java b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerTest.java new file mode 100644 index 00000000000..f96fb37c807 --- /dev/null +++ b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/DoubleSumAveragerTest.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +import java.util.HashMap; + +public class DoubleSumAveragerTest +{ + + @Test + public void testComputeResult() throws Exception + { + BaseAverager avg = new DoubleSumAverager(3, "test", "field", 1); + + Assert.assertEquals(0.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", 3.0), new HashMap<>()); + Assert.assertEquals(3.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", 3.0), new HashMap<>()); + Assert.assertEquals(6.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", new Integer(0)), new HashMap<>()); + Assert.assertEquals(6.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", 2.5), new HashMap<>()); + avg.addElement(Collections.singletonMap("field", 2.0), new HashMap<>()); + avg.addElement(Collections.singletonMap("field", 2.0), new HashMap<>()); + Assert.assertEquals(6.5, avg.computeResult(), 0.0); + + avg.skip(); + Assert.assertEquals(4.0, avg.computeResult(), 0.0); + + } + +} diff --git a/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactoryTest.java b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactoryTest.java new file mode 100644 index 00000000000..fb297adf8c5 --- /dev/null +++ b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerFactoryTest.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +import org.hamcrest.core.IsInstanceOf; +import org.junit.Assert; +import org.junit.Test; + +public class LongSumAveragerFactoryTest +{ + + @Test + public void testCreateAverager() + { + AveragerFactory fac = new LongSumAveragerFactory("test", 5, 1, "field"); + Assert.assertThat(fac.createAverager(), IsInstanceOf.instanceOf(LongSumAverager.class)); + } + +} diff --git a/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerTest.java b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerTest.java new file mode 100644 index 00000000000..b4631b5b4bf --- /dev/null +++ b/extensions-contrib/moving-average-query/src/test/java/org/apache/druid/query/movingaverage/averagers/LongSumAveragerTest.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.query.movingaverage.averagers; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +import java.util.HashMap; + +public class LongSumAveragerTest +{ + @Test + public void testComputeResult() + { + BaseAverager avg = new LongSumAverager(3, "test", "field", 1); + + Assert.assertEquals(0.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", 3L), new HashMap<>()); + Assert.assertEquals(3.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", 3L), new HashMap<>()); + Assert.assertEquals(6.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", 3), new HashMap<>()); + Assert.assertEquals(9.0, avg.computeResult(), 0.0); + + avg.addElement(Collections.singletonMap("field", 2L), new HashMap<>()); + avg.addElement(Collections.singletonMap("field", 2L), new HashMap<>()); + avg.addElement(Collections.singletonMap("field", 2L), new HashMap<>()); + Assert.assertEquals(6.0, avg.computeResult(), 0.0); + + avg.skip(); + Assert.assertEquals(4.0, avg.computeResult(), 0.0); + } +}