Moving Average extention: Add Sum averagers (#8511)

* Add sum averagers.

* avoid casting double to long.
This commit is contained in:
Eyal Yurman 2019-10-24 18:37:24 -05:00 committed by Jihoon Son
parent 774ce3ce6d
commit 14e33428f0
10 changed files with 366 additions and 0 deletions

View File

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

View File

@ -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)
})

View File

@ -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<Number, Double>
{
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;
}
}

View File

@ -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<Double, Double>
{
@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<Double> createAverager()
{
return new DoubleSumAverager(numBuckets, name, fieldName, cycleSize);
}
}

View File

@ -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<Number, Long>
{
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;
}
}

View File

@ -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<Long, Long>
{
@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<Long> createAverager()
{
return new LongSumAverager(numBuckets, name, fieldName, cycleSize);
}
}

View File

@ -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));
}
}

View File

@ -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<Number, Double> 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);
}
}

View File

@ -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));
}
}

View File

@ -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<Number, Long> 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);
}
}