You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dp...@apache.org on 2017/06/28 18:17:35 UTC
[12/20] lucene-solr:master: SOLR-10123: Upgraded the Analytics
Component to version 2.0
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java
new file mode 100644
index 0000000..5960c0e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java
@@ -0,0 +1,42 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function that casts any input to a {@link StringValue} or {@link StringValueStream}.
+ */
+public class StringCastFunction {
+ public static final String name = "string";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+ }
+ AnalyticsValueStream param = params[0];
+ if (param instanceof StringValueStream) {
+ return LambdaFunction.createStringLambdaFunction(name, a -> a, (StringValueStream)param);
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a string-castable parameter.");
+ }
+ });
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java
new file mode 100644
index 0000000..3a4e456
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java
@@ -0,0 +1,51 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A subtraction mapping function.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If two numeric Values are passed in, a {@link DoubleValue} representing the first subtracted by the second is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the Value subtracted by
+ * each of the values of the ValueStream for a document is returned.
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * </ul>
+ */
+public class SubtractFunction {
+ public static final String name = "sub";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 2) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+ }
+ AnalyticsValueStream param1 = params[0];
+ AnalyticsValueStream param2 = params[1];
+ if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a-b, (DoubleValueStream)param1, (DoubleValueStream)param2);
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+ }
+ });
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java
new file mode 100644
index 0000000..801d1ea
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java
@@ -0,0 +1,163 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A top mapping function, returning the highest value found.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a single comparable ValueStream is passed in, a Value (of the same type) representing the maximum of the values for each document is returned.
+ * <li>If multiple comparable Values are passed in, a Value (of the same type) representing the maximum of all values is returned.
+ * </ul>
+ */
+public class TopFunction {
+ public static final String name = "top";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length == 0) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires paramaters.");
+ }
+ AnalyticsValueStream param = params[0];
+ if (param instanceof DateValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a>b)? a:b, (DateValueStream)param);
+ }
+ DateValue[] castedParams = new DateValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof DateValue) {
+ castedParams[i] = (DateValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof IntValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a>b)? a:b, (IntValueStream)param);
+ }
+ IntValue[] castedParams = new IntValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof IntValue) {
+ castedParams[i] = (IntValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof LongValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a>b)? a:b, (LongValueStream)param);
+ }
+ LongValue[] castedParams = new LongValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof LongValue) {
+ castedParams[i] = (LongValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof FloatValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a>b)? a:b, (FloatValueStream)param);
+ }
+ FloatValue[] castedParams = new FloatValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof FloatValue) {
+ castedParams[i] = (FloatValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof DoubleValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a>b)? a:b, (DoubleValueStream)param);
+ }
+ DoubleValue[] castedParams = new DoubleValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof DoubleValue) {
+ castedParams[i] = (DoubleValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof StringValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)>=0)? a:b, (StringValueStream)param);
+ }
+ StringValue[] castedParams = new StringValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof StringValue) {
+ castedParams[i] = (StringValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)>=0)? a:b, castedParams, false);
+ }
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " +
+ "Incorrect parameter: "+params[0].getExpressionStr());
+ });
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java
new file mode 100644
index 0000000..3cf363b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Mapping functions to use for analytics expressions.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java
new file mode 100644
index 0000000..e21dd9b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Functions to use for analytics expressions.
+ */
+package org.apache.solr.analytics.function;
+
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java
new file mode 100644
index 0000000..a77f997
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java
@@ -0,0 +1,87 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.CountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.ExpressionCountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.TotalCountCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which either counts the number of values that the parameter expression contains,
+ * or the number of documents returned if no parameter is given.
+ */
+public class CountFunction extends AbstractLongValue implements ReductionFunction {
+ private CountCollector collector;
+ public static final String name = "count";
+ private final String exprStr;
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length == 0) {
+ return new CountFunction();
+ }
+ if (params.length == 1) {
+ return new CountFunction(params[0]);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function a max of 1 paramater, " + params.length + " given.");
+ });
+
+ public CountFunction() {
+ this.collector = new TotalCountCollector();
+ this.exprStr = AnalyticsValueStream.createExpressionString(name);
+ }
+
+ public CountFunction(AnalyticsValueStream param) {
+ this.collector = new ExpressionCountCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ return collector.count();
+ }
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (CountCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java
new file mode 100644
index 0000000..f009b59
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java
@@ -0,0 +1,87 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.CountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.ExpressionCountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.TotalCountCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which either counts the number of Solr Documents for which the parameter expression exists,
+ * or the number of documents returned if no parameter is given.
+ */
+public class DocCountFunction extends AbstractLongValue implements ReductionFunction {
+ private CountCollector collector;
+ public static final String name = "docCount";
+ private final String exprStr;
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length == 0) {
+ return new DocCountFunction();
+ }
+ if (params.length == 1) {
+ return new DocCountFunction(params[0]);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function accepts at most 1 paramater, " + params.length + " given.");
+ });
+
+ public DocCountFunction() {
+ this.collector = new TotalCountCollector();
+ this.exprStr = AnalyticsValueStream.createExpressionString(name);
+ }
+
+ public DocCountFunction(AnalyticsValueStream param) {
+ this.collector = new ExpressionCountCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ return collector.docCount();
+ }
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (CountCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java
new file mode 100644
index 0000000..f5ea12d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java
@@ -0,0 +1,298 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.DoubleMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.FloatMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.IntMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.LongMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.StringMaxCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the maximum value of the given expression.
+ */
+public class MaxFunction {
+ public static final String name = "max";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+ }
+ AnalyticsValueStream param = params[0];
+ if (param instanceof DateValueStream) {
+ return new DateMaxFunction((DateValueStream)param);
+ }
+ if (param instanceof IntValueStream) {
+ return new IntMaxFunction((IntValueStream)param);
+ }
+ if (param instanceof LongValueStream) {
+ return new LongMaxFunction((LongValueStream)param);
+ }
+ if (param instanceof FloatValueStream) {
+ return new FloatMaxFunction((FloatValueStream)param);
+ }
+ if (param instanceof DoubleValueStream) {
+ return new DoubleMaxFunction((DoubleValueStream)param);
+ }
+ if (param instanceof StringValueStream) {
+ return new StringMaxFunction((StringValueStream)param);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " +
+ "Incorrect parameter: "+params[0].getExpressionStr());
+ });
+}
+class IntMaxFunction extends AbstractIntValue implements ReductionFunction {
+ private IntMaxCollector collector;
+ public static final String name = MaxFunction.name;
+ private final String exprStr;
+
+ public IntMaxFunction(IntValueStream param) {
+ this.collector = new IntMaxCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public int getInt() {
+ return collector.exists() ? collector.max() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (IntMaxCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class LongMaxFunction extends AbstractLongValue implements ReductionFunction {
+ private LongMaxCollector collector;
+ public static final String name = MaxFunction.name;
+ private final String exprStr;
+
+ public LongMaxFunction(LongValueStream param) {
+ this.collector = new LongMaxCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ return collector.exists() ? collector.max() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (LongMaxCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class FloatMaxFunction extends AbstractFloatValue implements ReductionFunction {
+ private FloatMaxCollector collector;
+ public static final String name = MaxFunction.name;
+ private final String exprStr;
+
+ public FloatMaxFunction(FloatValueStream param) {
+ this.collector = new FloatMaxCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public float getFloat() {
+ return collector.exists() ? collector.max() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (FloatMaxCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DoubleMaxFunction extends AbstractDoubleValue implements ReductionFunction {
+ private DoubleMaxCollector collector;
+ public static final String name = MaxFunction.name;
+ private final String exprStr;
+
+ public DoubleMaxFunction(DoubleValueStream param) {
+ this.collector = new DoubleMaxCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public double getDouble() {
+ return collector.exists() ? collector.max() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (DoubleMaxCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DateMaxFunction extends AbstractDateValue implements ReductionFunction {
+ private LongMaxCollector collector;
+ public static final String name = MaxFunction.name;
+ private final String exprStr;
+
+ public DateMaxFunction(LongValueStream param) {
+ this.collector = new LongMaxCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ return collector.exists() ? collector.max() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (LongMaxCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class StringMaxFunction extends AbstractStringValue implements ReductionFunction {
+ private StringMaxCollector collector;
+ public static final String name = MaxFunction.name;
+ private final String exprStr;
+
+ public StringMaxFunction(StringValueStream param) {
+ this.collector = new StringMaxCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public String getString() {
+ return collector.exists() ? collector.max() : null;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (StringMaxCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java
new file mode 100644
index 0000000..9a6fe40
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java
@@ -0,0 +1,200 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedDoubleListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedFloatListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedIntListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedLongListCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the median value of the given expression.
+ */
+public class MedianFunction {
+ public static final String name = "median";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+ }
+ AnalyticsValueStream param = params[0];
+ if (param instanceof DateValueStream) {
+ return new DateMedianFunction((DateValueStream)param);
+ } else if (param instanceof IntValueStream) {
+ return new IntMedianFunction((IntValueStream)param);
+ } else if (param instanceof LongValueStream) {
+ return new LongMedianFunction((LongValueStream)param);
+ } else if (param instanceof FloatValueStream) {
+ return new FloatMedianFunction((FloatValueStream)param);
+ } else if (param instanceof DoubleValueStream) {
+ return new DoubleMedianFunction((DoubleValueStream)param);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a date or numeric parameter.");
+ });
+}
+abstract class NumericMedianFunction<T extends Comparable<T>> extends AbstractDoubleValue implements ReductionFunction {
+ protected SortedListCollector<T> collector;
+ public static final String name = MedianFunction.name;
+ private final String exprStr;
+
+ public NumericMedianFunction(DoubleValueStream param, SortedListCollector<T> collector) {
+ this.collector = collector;
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ protected abstract double collectOrd(int ord);
+
+ @Override
+ public double getDouble() {
+ int size = collector.size();
+ if (size == 0) {
+ return 0;
+ }
+ if (size % 2 == 0) {
+ return (collectOrd(size/2) + collectOrd(size/2 - 1))/2;
+ } else {
+ return collectOrd(size/2);
+ }
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedListCollector<T>)sync.apply(collector);
+ collector.calcMedian();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class IntMedianFunction extends NumericMedianFunction<Integer> {
+ public IntMedianFunction(IntValueStream param) {
+ super((DoubleValueStream) param, new SortedIntListCollector(param));
+ }
+
+ @Override
+ protected double collectOrd(int ord) {
+ return collector.get(ord);
+ }
+}
+class LongMedianFunction extends NumericMedianFunction<Long> {
+ public LongMedianFunction(LongValueStream param) {
+ super((DoubleValueStream) param, new SortedLongListCollector(param));
+ }
+
+ @Override
+ protected double collectOrd(int ord) {
+ return collector.get(ord);
+ }
+}
+class FloatMedianFunction extends NumericMedianFunction<Float> {
+ public FloatMedianFunction(FloatValueStream param) {
+ super((DoubleValueStream) param, new SortedFloatListCollector(param));
+ }
+
+ @Override
+ protected double collectOrd(int ord) {
+ return collector.get(ord);
+ }
+}
+class DoubleMedianFunction extends NumericMedianFunction<Double> {
+ public DoubleMedianFunction(DoubleValueStream param) {
+ super(param, new SortedDoubleListCollector(param));
+ }
+
+ @Override
+ protected double collectOrd(int ord) {
+ return collector.get(ord);
+ }
+}
+class DateMedianFunction extends AbstractDateValue implements ReductionFunction {
+ private SortedLongListCollector collector;
+ public static final String name = MedianFunction.name;
+ private final String exprStr;
+
+ public DateMedianFunction(DateValueStream param) {
+ this.collector = new SortedLongListCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ int size = collector.size();
+ if (size == 0) {
+ return 0;
+ }
+ if (size % 2 == 0) {
+ return (collector.get(size/2) + collector.get(size/2 - 1))/2;
+ } else {
+ return collector.get(size/2);
+ }
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedLongListCollector)sync.apply(collector);
+ collector.calcMedian();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java
new file mode 100644
index 0000000..92539d7
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java
@@ -0,0 +1,298 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.DoubleMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.FloatMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.IntMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.LongMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.StringMinCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the minumum value of the given expression.
+ */
+public class MinFunction {
+ public static final String name = "min";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+ }
+ AnalyticsValueStream param = params[0];
+ if (param instanceof DateValueStream) {
+ return new DateMinFunction((DateValueStream)param);
+ }
+ if (param instanceof IntValueStream) {
+ return new IntMinFunction((IntValueStream)param);
+ }
+ if (param instanceof LongValueStream) {
+ return new LongMinFunction((LongValueStream)param);
+ }
+ if (param instanceof FloatValueStream) {
+ return new FloatMinFunction((FloatValueStream)param);
+ }
+ if (param instanceof DoubleValueStream) {
+ return new DoubleMinFunction((DoubleValueStream)param);
+ }
+ if (param instanceof StringValueStream) {
+ return new StringMinFunction((StringValueStream)param);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " +
+ "Incorrect parameter: "+params[0].getExpressionStr());
+ });
+}
+class IntMinFunction extends AbstractIntValue implements ReductionFunction {
+ private IntMinCollector collector;
+ public static final String name = MinFunction.name;
+ private final String exprStr;
+
+ public IntMinFunction(IntValueStream param) {
+ this.collector = new IntMinCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public int getInt() {
+ return collector.exists() ? collector.min() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (IntMinCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class LongMinFunction extends AbstractLongValue implements ReductionFunction {
+ private LongMinCollector collector;
+ public static final String name = MinFunction.name;
+ private final String exprStr;
+
+ public LongMinFunction(LongValueStream param) {
+ this.collector = new LongMinCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ return collector.exists() ? collector.min() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (LongMinCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class FloatMinFunction extends AbstractFloatValue implements ReductionFunction {
+ private FloatMinCollector collector;
+ public static final String name = MinFunction.name;
+ private final String exprStr;
+
+ public FloatMinFunction(FloatValueStream param) {
+ this.collector = new FloatMinCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public float getFloat() {
+ return collector.exists() ? collector.min() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (FloatMinCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DoubleMinFunction extends AbstractDoubleValue implements ReductionFunction {
+ private DoubleMinCollector collector;
+ public static final String name = MinFunction.name;
+ private final String exprStr;
+
+ public DoubleMinFunction(DoubleValueStream param) {
+ this.collector = new DoubleMinCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public double getDouble() {
+ return collector.exists() ? collector.min() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (DoubleMinCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DateMinFunction extends AbstractDateValue implements ReductionFunction {
+ private LongMinCollector collector;
+ public static final String name = MinFunction.name;
+ private final String exprStr;
+
+ public DateMinFunction(LongValueStream param) {
+ this.collector = new LongMinCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ return collector.exists() ? collector.min() : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (LongMinCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class StringMinFunction extends AbstractStringValue implements ReductionFunction {
+ private StringMinCollector collector;
+ public static final String name = MinFunction.name;
+ private final String exprStr;
+
+ public StringMinFunction(StringValueStream param) {
+ this.collector = new StringMinCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public String getString() {
+ return collector.exists() ? collector.min() : null;
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (StringMinCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java
new file mode 100644
index 0000000..5fa7e64
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java
@@ -0,0 +1,76 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.ExpressionCountCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the number of documents for which the given expression does not exist.
+ */
+public class MissingFunction extends AbstractLongValue implements ReductionFunction {
+ private ExpressionCountCollector collector;
+ public static final String name = "missing";
+ private final String exprStr;
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+ }
+ return new MissingFunction(params[0]);
+ });
+
+ public MissingFunction(AnalyticsValueStream param) {
+ this.collector = new ExpressionCountCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public long getLong() {
+ return collector.missing();
+ }
+ @Override
+ public boolean exists() {
+ return true;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (ExpressionCountCollector)sync.apply(collector);
+ }
+
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java
new file mode 100644
index 0000000..0b86cdf
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java
@@ -0,0 +1,386 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.Locale;
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedDoubleListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedFloatListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedIntListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedLongListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedStringListCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.constant.ConstantIntValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the given ordinal of the sorted values of the given expression.
+ */
+public class OrdinalFunction {
+ public static final String name = "ordinal";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 2) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramater, " + params.length + " found.");
+ }
+ AnalyticsValueStream percValue = params[0];
+ int ord = 0;
+ if (params[0] instanceof ConstantIntValue) {
+ ord = ((IntValue)percValue).getInt();
+ if (ord == 0) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires the ordinal to be >= 1 or <= -1, 0 is not accepted.");
+ }
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a constant int value (the ordinal) as the first argument.");
+ }
+ AnalyticsValueStream param = params[1];
+ if (param instanceof DateValueStream) {
+ return new DateOrdinalFunction((DateValueStream)param, ord);
+ }else if (param instanceof IntValueStream) {
+ return new IntOrdinalFunction((IntValueStream)param, ord);
+ } else if (param instanceof LongValueStream) {
+ return new LongOrdinalFunction((LongValueStream)param, ord);
+ } else if (param instanceof FloatValueStream) {
+ return new FloatOrdinalFunction((FloatValueStream)param, ord);
+ } else if (param instanceof DoubleValueStream) {
+ return new DoubleOrdinalFunction((DoubleValueStream)param, ord);
+ } else if (param instanceof StringValueStream) {
+ return new StringOrdinalFunction((StringValueStream)param, ord);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter.");
+ });
+
+ protected static String createOrdinalExpressionString(AnalyticsValueStream param, double perc) {
+ return String.format(Locale.ROOT, "%s(%s,%s)",
+ name,
+ (int)(perc*100),
+ param.getExpressionStr());
+ }
+}
+class IntOrdinalFunction extends AbstractIntValue implements ReductionFunction {
+ private SortedIntListCollector collector;
+ private int ordinal;
+ public static final String name = OrdinalFunction.name;
+ private final String exprStr;
+
+ public IntOrdinalFunction(IntValueStream param, int ordinal) {
+ this.collector = new SortedIntListCollector(param);
+ this.ordinal = ordinal;
+ this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+ }
+
+ @Override
+ public int getInt() {
+ int size = collector.size();
+ if (ordinal > 0) {
+ return ordinal <= size ? collector.get(ordinal - 1) : 0;
+ } else {
+ return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+ }
+
+ }
+ @Override
+ public boolean exists() {
+ return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedIntListCollector)sync.apply(collector);
+ if (ordinal > 0) {
+ collector.calcOrdinal(ordinal);
+ } else {
+ collector.calcReverseOrdinal(ordinal*-1);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class LongOrdinalFunction extends AbstractLongValue implements ReductionFunction {
+ private SortedLongListCollector collector;
+ private int ordinal;
+ public static final String name = OrdinalFunction.name;
+ private final String exprStr;
+
+ public LongOrdinalFunction(LongValueStream param, int ordinal) {
+ this.collector = new SortedLongListCollector(param);
+ this.ordinal = ordinal;
+ this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+ }
+
+ @Override
+ public long getLong() {
+ int size = collector.size();
+ if (ordinal > 0) {
+ return ordinal <= size ? collector.get(ordinal - 1) : 0;
+ } else {
+ return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+ }
+
+ }
+ @Override
+ public boolean exists() {
+ return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedLongListCollector)sync.apply(collector);
+ if (ordinal > 0) {
+ collector.calcOrdinal(ordinal);
+ } else {
+ collector.calcReverseOrdinal(ordinal*-1);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class FloatOrdinalFunction extends AbstractFloatValue implements ReductionFunction {
+ private SortedFloatListCollector collector;
+ private int ordinal;
+ public static final String name = OrdinalFunction.name;
+ private final String exprStr;
+
+ public FloatOrdinalFunction(FloatValueStream param, int ordinal) {
+ this.collector = new SortedFloatListCollector(param);
+ this.ordinal = ordinal;
+ this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+ }
+
+ @Override
+ public float getFloat() {
+ int size = collector.size();
+ if (ordinal > 0) {
+ return ordinal <= size ? collector.get(ordinal - 1) : 0;
+ } else {
+ return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+ }
+
+ }
+ @Override
+ public boolean exists() {
+ return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedFloatListCollector)sync.apply(collector);
+ if (ordinal > 0) {
+ collector.calcOrdinal(ordinal);
+ } else {
+ collector.calcReverseOrdinal(ordinal*-1);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DoubleOrdinalFunction extends AbstractDoubleValue implements ReductionFunction {
+ private SortedDoubleListCollector collector;
+ private int ordinal;
+ public static final String name = OrdinalFunction.name;
+ private final String exprStr;
+
+ public DoubleOrdinalFunction(DoubleValueStream param, int ordinal) {
+ this.collector = new SortedDoubleListCollector(param);
+ this.ordinal = ordinal;
+ this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+ }
+
+ @Override
+ public double getDouble() {
+ int size = collector.size();
+ if (ordinal > 0) {
+ return ordinal <= size ? collector.get(ordinal - 1) : 0;
+ } else {
+ return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+ }
+
+ }
+ @Override
+ public boolean exists() {
+ return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedDoubleListCollector)sync.apply(collector);
+ if (ordinal > 0) {
+ collector.calcOrdinal(ordinal);
+ } else {
+ collector.calcReverseOrdinal(ordinal*-1);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DateOrdinalFunction extends AbstractDateValue implements ReductionFunction {
+ private SortedLongListCollector collector;
+ private int ordinal;
+ public static final String name = OrdinalFunction.name;
+ private final String exprStr;
+
+ public DateOrdinalFunction(LongValueStream param, int ordinal) {
+ this.collector = new SortedLongListCollector(param);
+ this.ordinal = ordinal;
+ this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+ }
+
+ @Override
+ public long getLong() {
+ int size = collector.size();
+ if (ordinal > 0) {
+ return ordinal <= size ? collector.get(ordinal - 1) : 0;
+ } else {
+ return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+ }
+
+ }
+ @Override
+ public boolean exists() {
+ return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedLongListCollector)sync.apply(collector);
+ collector.calcOrdinal(ordinal);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class StringOrdinalFunction extends AbstractStringValue implements ReductionFunction {
+ private SortedStringListCollector collector;
+ private int ordinal;
+ public static final String name = OrdinalFunction.name;
+ private final String exprStr;
+
+ public StringOrdinalFunction(StringValueStream param, int ordinal) {
+ this.collector = new SortedStringListCollector(param);
+ this.ordinal = ordinal;
+ this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+ }
+
+ @Override
+ public String getString() {
+ int size = collector.size();
+ if (ordinal > 0) {
+ return ordinal <= size ? collector.get(ordinal - 1) : null;
+ } else {
+ return (ordinal * -1) <= size ? collector.get(size + ordinal) : null;
+ }
+
+ }
+ @Override
+ public boolean exists() {
+ return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedStringListCollector)sync.apply(collector);
+ if (ordinal > 0) {
+ collector.calcOrdinal(ordinal);
+ } else {
+ collector.calcReverseOrdinal(ordinal*-1);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java
new file mode 100644
index 0000000..4277d90
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java
@@ -0,0 +1,337 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.util.Locale;
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedDoubleListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedFloatListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedIntListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedLongListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedStringListCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.constant.ConstantIntValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the given percentile of the sorted values of the given expression.
+ */
+public class PercentileFunction {
+ public static final String name = "percentile";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 2) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramater, " + params.length + " found.");
+ }
+ AnalyticsValueStream percValue = params[0];
+ double perc = 0;
+ if (percValue instanceof ConstantIntValue) {
+ perc = ((IntValue)percValue).getInt();
+ if (perc < 0 || perc > 99) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a percentile between 0 and 99, " + ((int)perc) + " found.");
+ }
+ perc /= 100;
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a constant int value (the percentile) as the first argument.");
+ }
+ AnalyticsValueStream param = params[1];
+ if (param instanceof DateValueStream) {
+ return new DatePercentileFunction((DateValueStream)param, perc);
+ }else if (param instanceof IntValueStream) {
+ return new IntPercentileFunction((IntValueStream)param, perc);
+ } else if (param instanceof LongValueStream) {
+ return new LongPercentileFunction((LongValueStream)param, perc);
+ } else if (param instanceof FloatValueStream) {
+ return new FloatPercentileFunction((FloatValueStream)param, perc);
+ } else if (param instanceof DoubleValueStream) {
+ return new DoublePercentileFunction((DoubleValueStream)param, perc);
+ } else if (param instanceof StringValueStream) {
+ return new StringPercentileFunction((StringValueStream)param, perc);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter.");
+ });
+
+ protected static String createPercentileExpressionString(AnalyticsValueStream param, double perc) {
+ return String.format(Locale.ROOT, "%s(%s,%s)",
+ name,
+ (int)(perc*100),
+ param.getExpressionStr());
+ }
+}
+class IntPercentileFunction extends AbstractIntValue implements ReductionFunction {
+ private SortedIntListCollector collector;
+ private double percentile;
+ public static final String name = PercentileFunction.name;
+ private final String exprStr;
+
+ public IntPercentileFunction(IntValueStream param, double percentile) {
+ this.collector = new SortedIntListCollector(param);
+ this.percentile = percentile;
+ this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+ }
+
+ @Override
+ public int getInt() {
+ int size = collector.size();
+ return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedIntListCollector)sync.apply(collector);
+ collector.calcPercentile(percentile);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class LongPercentileFunction extends AbstractLongValue implements ReductionFunction {
+ private SortedLongListCollector collector;
+ private double percentile;
+ public static final String name = PercentileFunction.name;
+ private final String exprStr;
+
+ public LongPercentileFunction(LongValueStream param, double percentile) {
+ this.collector = new SortedLongListCollector(param);
+ this.percentile = percentile;
+ this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+ }
+
+ @Override
+ public long getLong() {
+ int size = collector.size();
+ return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedLongListCollector)sync.apply(collector);
+ collector.calcPercentile(percentile);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class FloatPercentileFunction extends AbstractFloatValue implements ReductionFunction {
+ private SortedFloatListCollector collector;
+ private double percentile;
+ public static final String name = PercentileFunction.name;
+ private final String exprStr;
+
+ public FloatPercentileFunction(FloatValueStream param, double percentile) {
+ this.collector = new SortedFloatListCollector(param);
+ this.percentile = percentile;
+ this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+ }
+
+ @Override
+ public float getFloat() {
+ int size = collector.size();
+ return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedFloatListCollector)sync.apply(collector);
+ collector.calcPercentile(percentile);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DoublePercentileFunction extends AbstractDoubleValue implements ReductionFunction {
+ private SortedDoubleListCollector collector;
+ private double percentile;
+ public static final String name = PercentileFunction.name;
+ private final String exprStr;
+
+ public DoublePercentileFunction(DoubleValueStream param, double percentile) {
+ this.collector = new SortedDoubleListCollector(param);
+ this.percentile = percentile;
+ this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+ }
+
+ @Override
+ public double getDouble() {
+ int size = collector.size();
+ return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedDoubleListCollector)sync.apply(collector);
+ collector.calcPercentile(percentile);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class DatePercentileFunction extends AbstractDateValue implements ReductionFunction {
+ private SortedLongListCollector collector;
+ private double percentile;
+ public static final String name = PercentileFunction.name;
+ private final String exprStr;
+
+ public DatePercentileFunction(LongValueStream param, double percentile) {
+ this.collector = new SortedLongListCollector(param);
+ this.percentile = percentile;
+ this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+ }
+
+ @Override
+ public long getLong() {
+ int size = collector.size();
+ return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedLongListCollector)sync.apply(collector);
+ collector.calcPercentile(percentile);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
+class StringPercentileFunction extends AbstractStringValue implements ReductionFunction {
+ private SortedStringListCollector collector;
+ private double percentile;
+ public static final String name = PercentileFunction.name;
+ private final String exprStr;
+
+ public StringPercentileFunction(StringValueStream param, double percentile) {
+ this.collector = new SortedStringListCollector(param);
+ this.percentile = percentile;
+ this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+ }
+
+ @Override
+ public String getString() {
+ int size = collector.size();
+ return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : null;
+ }
+ @Override
+ public boolean exists() {
+ return collector.size() > 0;
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SortedStringListCollector)sync.apply(collector);
+ collector.calcPercentile(percentile);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java
new file mode 100644
index 0000000..7d4e939
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java
@@ -0,0 +1,92 @@
+/*
+ * 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.solr.analytics.function.reduction;
+
+import java.io.Serializable;
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SumCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the sum of the sorted values of the given expression.
+ */
+public class SumFunction extends AbstractDoubleValue implements ReductionFunction {
+ private SumCollector collector;
+ public static final String name = "sum";
+ private final String exprStr;
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+ }
+ DoubleValueStream casted;
+ try {
+ casted = (DoubleValueStream) params[0];
+ }
+ catch (ClassCastException e) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameter. " +
+ "Incorrect parameter: "+params[0].getExpressionStr());
+ }
+ return new SumFunction(casted);
+ });
+
+ public SumFunction(DoubleValueStream param) {
+ this.collector = new SumCollector(param);
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ }
+
+ @Override
+ public double getDouble() {
+ return collector.sum();
+ }
+ @Override
+ public boolean exists() {
+ return collector.exists();
+ }
+
+ @Override
+ public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+ collector = (SumCollector) sync.apply(collector);
+ }
+
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.REDUCTION;
+ }
+
+ protected static class SumData extends ReductionData implements Serializable {
+ private static final long serialVersionUID = 5920718235872898338L;
+ double sum;
+ }
+}
\ No newline at end of file