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:40 UTC
[17/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/facet/compare/ConstantComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ConstantComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ConstantComparator.java
new file mode 100644
index 0000000..ece09f8
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ConstantComparator.java
@@ -0,0 +1,30 @@
+/*
+ * 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.facet.compare;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A results comparator that compares constants.
+ */
+public class ConstantComparator extends FacetResultsComparator {
+
+ @Override
+ public int compare(FacetBucket b1, FacetBucket b2) {
+ return 0;
+ }
+}
\ 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/facet/compare/DelegatingComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/DelegatingComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/DelegatingComparator.java
new file mode 100644
index 0000000..200e68b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/DelegatingComparator.java
@@ -0,0 +1,62 @@
+/*
+ * 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.facet.compare;
+
+import java.util.Collection;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A comparator used to sort the facet-value buckets of facet, using the delegate comparator if two values are equal.
+ */
+public class DelegatingComparator extends FacetResultsComparator {
+ private final Iterable<FacetResultsComparator> comparators;
+
+ /**
+ * Create a delegating results comparator. This comparator will in succession use the given comparators, continuing if the values are equal.
+ * Two buckets are considered equal if and only if all comparators find them equal
+ *
+ * @param comparators the comparators to use in succession
+ */
+ private DelegatingComparator(Iterable<FacetResultsComparator> comparators) {
+ this.comparators = comparators;
+ }
+
+ public static FacetResultsComparator joinComparators(Collection<FacetResultsComparator> comparators) throws SolrException {
+ if (comparators.size() == 0) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"A sort must have at least 1 comparator criteria.");
+ } else if (comparators.size() == 1) {
+ return comparators.iterator().next();
+ } else {
+ return new DelegatingComparator(comparators);
+ }
+ }
+
+ @Override
+ public int compare(FacetBucket b1, FacetBucket b2) {
+ int val = 0;
+ for (FacetResultsComparator comparator : comparators) {
+ val = comparator.compare(b1, b2);
+ if (val != 0) {
+ break;
+ }
+ }
+ return val;
+ }
+}
\ 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/facet/compare/ExpressionComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ExpressionComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ExpressionComparator.java
new file mode 100644
index 0000000..e4c1940
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ExpressionComparator.java
@@ -0,0 +1,46 @@
+/*
+ * 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.facet.compare;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A comparator used to sort the facet-value buckets of facet.
+ */
+public class ExpressionComparator<T extends Comparable<T>> extends FacetResultsComparator {
+ private final String expression;
+
+ /**
+ * Create an entry comparator comparing the given expression.
+ *
+ * @param expression the name of the expression results to compare
+ */
+ public ExpressionComparator(String expression) {
+ this.expression = expression;
+ }
+
+ @SuppressWarnings("unchecked")
+ public int compare(FacetBucket b1, FacetBucket b2) {
+ T t1 = (T)b1.getResult(expression);
+ T t2 = (T)b2.getResult(expression);
+ if (t1 == null || t2 == null) {
+ return Boolean.compare(t2 == null, t1 == null) * resultMult;
+ } else {
+ return t1.compareTo(t2) * resultMult;
+ }
+ }
+}
\ 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/facet/compare/FacetResultsComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetResultsComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetResultsComparator.java
new file mode 100644
index 0000000..9303f21
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetResultsComparator.java
@@ -0,0 +1,52 @@
+/*
+ * 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.facet.compare;
+
+import java.util.Comparator;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A comparator used to sort the buckets of facet.
+ */
+public abstract class FacetResultsComparator implements Comparator<FacetBucket> {
+ protected int resultMult;
+
+ /**
+ * Create a results comparator assuming an ascending ordering.
+ */
+ public FacetResultsComparator() {
+ setDirection(true);
+ }
+
+ /**
+ * Set the order direction for comparison.
+ *
+ * @param ascending whether to compare using an ascending ordering
+ */
+ public void setDirection(boolean ascending) {
+ this.resultMult = ascending ? 1 : -1;
+ }
+
+ /**
+ * Compare one facet bucket to another.
+ *
+ * @param b1 the first bucket to compare
+ * @param b2 the second bucket to compare
+ */
+ public abstract int compare(FacetBucket b1, FacetBucket b2);
+}
\ 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/facet/compare/FacetValueComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetValueComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetValueComparator.java
new file mode 100644
index 0000000..a07ac7b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetValueComparator.java
@@ -0,0 +1,37 @@
+/*
+ * 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.facet.compare;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A results comparator that compares the name of facet value buckets, which is the string value of the facet value.
+ */
+public class FacetValueComparator extends FacetResultsComparator {
+
+ /**
+ * Create a facet value comparator.
+ */
+ public FacetValueComparator() {
+ super();
+ }
+
+ @Override
+ public int compare(FacetBucket b1, FacetBucket b2) {
+ return b1.getFacetValue().compareTo(b2.getFacetValue()) * resultMult;
+ }
+}
\ 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/facet/compare/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/package-info.java
new file mode 100644
index 0000000..c86ad17
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/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.
+ */
+
+/**
+ * Comparators used to sort the buckets of an analytics facet.
+ */
+package org.apache.solr.analytics.facet.compare;
+
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/package-info.java
new file mode 100644
index 0000000..5812e54
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/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.
+ */
+
+/**
+ * Facets supported by the analytics component.
+ */
+package org.apache.solr.analytics.facet;
+
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java
new file mode 100644
index 0000000..3c44555
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java
@@ -0,0 +1,71 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.analytics.AnalyticsExpression;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ * A class used to generate results for a list of {@link AnalyticsExpression}s.
+ */
+public class ExpressionCalculator {
+ private final Iterable<AnalyticsExpression> expressions;
+
+ public ExpressionCalculator(Iterable<AnalyticsExpression> expressions) {
+ this.expressions = expressions;
+ }
+
+ /**
+ * Calculate results for the list of {@link AnalyticsExpression}s.
+ * <p>
+ * NOTE: This method can, and is, called multiple times to generate different responses.
+ * <br>
+ * The results are determined by which {@link ReductionDataCollection} is passed to the {@link ReductionCollectionManager#setData}
+ * method of the {@link ReductionCollectionManager} managing the reduction for the list of {@link AnalyticsExpression}s.
+ *
+ * @return a {@link NamedList} containing the results
+ */
+ public Map<String,Object> getResults() {
+ Map<String,Object> exprVals = new HashMap<>();
+ expressions.forEach(expr -> {
+ Object obj = expr.toObject();
+ if (expr.exists()) {
+ exprVals.put(expr.getName(), obj);
+ }
+ });
+ return exprVals;
+ }
+
+ /**
+ * Calculate results for the list of {@link AnalyticsExpression}s and add them to the given response.
+ * <p>
+ * NOTE: This method can, and is, called multiple times to generate different responses.
+ * <br>
+ * The results are determined by which {@link ReductionDataCollection} is passed to the {@link ReductionCollectionManager#setData}
+ * method of the {@link ReductionCollectionManager} managing the reduction for the list of {@link AnalyticsExpression}s.
+ *
+ * @param response the response to add the results map to.
+ */
+ public void addResults(Map<String,Object> response) {
+ response.put(AnalyticsResponseHeadings.RESULTS, getResults());
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java
new file mode 100644
index 0000000..1402a76
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import org.apache.solr.analytics.function.field.AnalyticsField;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+
+/**
+ * The {@link ReductionCollectionManager} used for distributed requests.
+ */
+public class MergingReductionCollectionManager extends ReductionCollectionManager {
+
+ public MergingReductionCollectionManager() {
+ super();
+ }
+
+ public MergingReductionCollectionManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+ super(reductionDataCollectors, fields);
+ }
+
+ @Override
+ protected ReductionCollectionManager createNewManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+ return new MergingReductionCollectionManager(reductionDataCollectors,fields);
+ }
+
+ @Override
+ public void setData(ReductionDataCollection dataCollection) {
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].setMergedData(dataCollection.dataArr[i]);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java
new file mode 100644
index 0000000..b3a178c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java
@@ -0,0 +1,320 @@
+/*
+ * 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;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.solr.analytics.function.field.AnalyticsField;
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.stream.reservation.read.ReductionDataReader;
+import org.apache.solr.analytics.stream.reservation.write.ReductionDataWriter;
+import org.apache.solr.analytics.value.AnalyticsValue;
+
+/**
+ * The manager of reduction collection.
+ * Contains a group of {@link ReductionDataCollector}s which will be updated together.
+ * <p>
+ * The manager assumes a non-distributed request. {@link MergingReductionCollectionManager} is used for distributed requests.
+ */
+public class ReductionCollectionManager {
+ protected final ReductionDataCollector<?>[] reductionDataCollectors;
+ private final List<ReductionDataReservation<?,?>> reservations;
+
+ private final List<ReductionDataReader<?>> readers;
+ private final List<ReductionDataWriter<?>> writers;
+
+ private final Iterable<AnalyticsField> fields;
+
+ public ReductionCollectionManager() {
+ this(new ReductionDataCollector<?>[0], new ArrayList<>(0));
+ }
+
+ /**
+ * Create a Manager to oversee the given {@link ReductionDataCollector}s.
+ *
+ * @param reductionDataCollectors array of collectors that are collecting over the same set of data
+ * @param fields all fields used by the given collectors
+ */
+ public ReductionCollectionManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+ this.reductionDataCollectors = reductionDataCollectors;
+ Arrays.sort(reductionDataCollectors, (a,b) -> a.getExpressionStr().compareTo(b.getExpressionStr()));
+
+ reservations = new LinkedList<>();
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].submitReservations(reservation -> reservations.add(reservation));
+ }
+
+ this.fields = fields;
+
+ this.readers = new ArrayList<>();
+ this.writers = new ArrayList<>();
+ }
+
+ /**
+ * Return whether or not the manager needs collection done, which is false if no collectors are
+ * being managed and true if at least one is.
+ *
+ * @return true if at least one collector is being managed
+ */
+ public boolean needsCollection() {
+ return reductionDataCollectors.length > 0;
+ }
+
+ /**
+ * Merge this collection manager with others.
+ *
+ * @param reductionManagers the collection managers to merge with
+ * @return a collection manager that manages the union of data collectors from this class and the given managers
+ */
+ public ReductionCollectionManager merge(Iterable<ReductionCollectionManager> reductionManagers) {
+ HashMap<String,ReductionDataCollector<?>> mergedCollectors = new HashMap<>();
+ HashMap<String,AnalyticsField> mergedFields = new HashMap<>();
+
+ for (ReductionDataCollector<?> collector : reductionDataCollectors) {
+ mergedCollectors.put(collector.getExpressionStr(), collector);
+ }
+ fields.forEach( field -> mergedFields.put(field.getExpressionStr(), field) );
+
+ reductionManagers.forEach( manager -> {
+ for (ReductionDataCollector<?> collector : manager.reductionDataCollectors) {
+ mergedCollectors.put(collector.getExpressionStr(), collector);
+ }
+ manager.fields.forEach( field -> mergedFields.put(field.getExpressionStr(), field) );
+ });
+ ReductionDataCollector<?>[] collectors = new ReductionDataCollector<?>[mergedCollectors.size()];
+ mergedCollectors.values().toArray(collectors);
+ return createNewManager(collectors, mergedFields.values());
+ }
+
+ /**
+ * Create an {@link ReductionCollectionManager} to manage the given collectors and fields.
+ *
+ * @param reductionDataCollectors Reduction collectors
+ * @param fields fields used by the reductions
+ * @return a collection manager
+ */
+ protected ReductionCollectionManager createNewManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+ return new ReductionCollectionManager(reductionDataCollectors,fields);
+ }
+
+ /**
+ * Get the {@link AnalyticsField}s used in the managed expressions.
+ *
+ * @return the fields used
+ */
+ public Iterable<AnalyticsField> getUsedFields() {
+ return fields;
+ }
+
+ /**
+ * Set the context of the readers of the used {@link AnalyticsField}s.
+ *
+ * @param context the reader context
+ * @throws IOException if an error occurs while setting the fields' context
+ */
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ for (AnalyticsField field : fields) {
+ field.doSetNextReader(context);
+ }
+ }
+
+ /**
+ * Collect the values from the used {@link AnalyticsField}s.
+ *
+ * @param doc the document to collect values for
+ * @throws IOException if an error occurs during field collection
+ */
+ public void collect(int doc) throws IOException {
+ for (AnalyticsField field : fields) {
+ field.collect(doc);
+ }
+ }
+
+ /**
+ * Add a {@link ReductionDataCollection} to target while collecting documents.
+ * This target is valid until the lasting targets are cleared.
+ *
+ * @param target data collection to add document data too
+ */
+ public void addLastingCollectTarget(ReductionDataCollection target) {
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].addLastingCollectTarget(target.dataArr[i]);
+ }
+ }
+ /**
+ * Clear lasting collection targets.
+ */
+ public void clearLastingCollectTargets() {
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].clearLastingCollectTargets();
+ }
+ }
+
+ /**
+ * Add a new {@link ReductionDataCollection} to target while collecting the next document.
+ * This target is only valid for the next {@link #apply()} call.
+ *
+ * @return the new data collection being targeted
+ */
+ public ReductionDataCollection newDataCollectionTarget() {
+ ReductionDataCollection newCol = new ReductionDataCollection();
+ newCol.dataArr = new ReductionData[reductionDataCollectors.length];
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ newCol.dataArr[i] = reductionDataCollectors[i].newDataTarget();
+ }
+ return newCol;
+ }
+ /**
+ * Add a {@link ReductionDataCollection} to target while collecting the next document.
+ * This target is only valid for the next {@link #apply()} call.
+ *
+ * @param target data collection to add document data too
+ */
+ public void addCollectTarget(ReductionDataCollection target) {
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].addCollectTarget(target.dataArr[i]);
+ }
+ }
+
+ /**
+ * Apply the values of the collected fields through the expressions' logic to the managed data collectors.
+ * This is called after {@link #collect(int)} has been called and the collection targets have been added.
+ */
+ public void apply() {
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].collectAndApply();;
+ }
+ }
+
+ /**
+ * Finalize the reductions with the collected data stored in the parameter.
+ * Once the data is finalized, the {@link ReductionFunction}s that use these
+ * {@link ReductionDataCollector}s act like regular {@link AnalyticsValue} classes that
+ * can be accessed through their {@code get<value-type>} methods.
+ *
+ * @param dataCollection the collection of reduction data to compute results for
+ */
+ public void setData(ReductionDataCollection dataCollection) {
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].setData(dataCollection.dataArr[i]);
+ }
+ }
+
+ /**
+ * Construct a new data collection holding data for all managed data collectors.
+ *
+ * @return a new data collection
+ */
+ public ReductionDataCollection newDataCollection() {
+ ReductionDataCollection newCol = new ReductionDataCollection();
+ newCol.dataArr = new ReductionData[reductionDataCollectors.length];
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ newCol.dataArr[i] = reductionDataCollectors[i].newData();
+ }
+ return newCol;
+ }
+
+ /**
+ * Sets the stream of shard data to merge with.
+ *
+ * @param input the stream of shard data
+ */
+ public void setShardInput(DataInput input) {
+ readers.clear();
+ reservations.forEach( resv -> readers.add(resv.createReadStream(input)));
+ }
+ /**
+ * Merge the data from the given shard input stream into the set IO data collectors.
+ * Should always be called after {@link #setShardInput(DataInput)} and either {@link #prepareReductionDataIO(ReductionDataCollection)}
+ * or {@link #newDataCollectionIO()} have been called.
+ *
+ * @throws IOException if an error occurs while reading the shard data
+ */
+ public void mergeData() throws IOException {
+ for (ReductionDataReader<?> reader : readers) {
+ reader.read();
+ }
+ }
+
+ /**
+ * Sets the stream to export shard data to.
+ *
+ * @param output the stream of shard data
+ */
+ public void setShardOutput(DataOutput output) {
+ writers.clear();
+ reservations.forEach( resv -> writers.add(resv.createWriteStream(output)));
+ }
+ /**
+ * Export the data from the set IO data collectors to the given shard output stream.
+ * Should always be called after {@link #setShardOutput(DataOutput)} and {@link #prepareReductionDataIO(ReductionDataCollection)}.
+ *
+ * @throws IOException if an error occurs while writing the shard data
+ */
+ public void exportData() throws IOException {
+ for (ReductionDataWriter<?> writer : writers) {
+ writer.write();
+ }
+ }
+
+ /**
+ * Set the given data collection to be used for either merging or exporting
+ *
+ * @param col collection to export from or merge to
+ */
+ public void prepareReductionDataIO(ReductionDataCollection col) {
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ reductionDataCollectors[i].dataIO(col.dataArr[i]);
+ }
+ }
+
+ /**
+ * Create a new {@link ReductionDataCollection} to merge to or export from.
+ * Mainly used for creating facet value collectors when merging shard data.
+ *
+ * @return the new data collection created
+ */
+ public ReductionDataCollection newDataCollectionIO() {
+ ReductionDataCollection newCol = new ReductionDataCollection();
+ newCol.dataArr = new ReductionData[reductionDataCollectors.length];
+ for (int i = 0; i < reductionDataCollectors.length; i++) {
+ newCol.dataArr[i] = reductionDataCollectors[i].newDataIO();
+ }
+ return newCol;
+ }
+
+ /**
+ * Holds the collection of {@link ReductionData} that will be updated together.
+ *
+ * For example each grouping will have a separate {@link ReductionDataCollection}, and
+ * ungrouped expressions will have their own as well.
+ */
+ public static class ReductionDataCollection{
+ public ReductionData[] dataArr;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java
new file mode 100644
index 0000000..fea01c2
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.value.AnalyticsValue;
+
+/**
+ * A function that reduces the values of a mapping expression, field or constant.
+ */
+public interface ReductionFunction extends AnalyticsValue {
+
+ /**
+ * Syncs the data collectors with shared versions across the entire Analytics Request
+ * so that as little data as possible is sent across shards.
+ *
+ * @param sync a function that takes in a {@link ReductionDataCollector} and returns a shared version
+ */
+ void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync);
+}
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java
new file mode 100644
index 0000000..dab0358
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java
@@ -0,0 +1,69 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+
+/**
+ * An analytics wrapper for Solr Fields.
+ *
+ * Currently only fields with Doc Values enabled can be used in Analytics queries.
+ */
+public abstract class AnalyticsField implements AnalyticsValueStream {
+ protected static final int initialArrayLength = 20;
+
+ protected final String fieldName;
+
+ protected AnalyticsField(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ @Override
+ public String getExpressionStr() {
+ return fieldName;
+ }
+
+ @Override
+ public String getName() {
+ return fieldName;
+ }
+
+ @Override
+ public ExpressionType getExpressionType() {
+ return ExpressionType.FIELD;
+ }
+
+ /**
+ * Set the segment reader context
+ *
+ * @param context segment context
+ * @throws IOException if an error occurs while loading the leaf reader
+ */
+ public abstract void doSetNextReader(LeafReaderContext context) throws IOException;
+
+ /**
+ * Collect the value(s) of the wrapped field for the given document, and store the value.
+ *
+ * @param doc ID of the document to collect
+ * @throws IOException if an error occurs while reading the document.
+ */
+ public abstract void collect(int doc) throws IOException;
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java
new file mode 100644
index 0000000..650bc36
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java
@@ -0,0 +1,111 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedDocValues;
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.value.BooleanValue.CastingBooleanValue;
+import org.apache.solr.schema.BoolField;
+
+/**
+ * An analytics wrapper for a single-valued {@link BoolField} with DocValues enabled.
+ */
+public class BooleanField extends AnalyticsField implements CastingBooleanValue {
+ private SortedDocValues docValues;
+ boolean value;
+ boolean exists;
+ int trueOrd;
+
+ public BooleanField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSorted(context.reader(), fieldName);
+
+ // figure out what ord maps to true
+ int numOrds = docValues.getValueCount();
+ // if no values in the segment, default trueOrd to something other then -1 (missing)
+ int trueOrd = -2;
+ for (int i=0; i<numOrds; i++) {
+ final BytesRef br = docValues.lookupOrd(i);
+ if (br.length==1 && br.bytes[br.offset]=='T') {
+ trueOrd = i;
+ break;
+ }
+ }
+
+ this.trueOrd = trueOrd;
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ exists = docValues.advanceExact(doc);
+ if (exists) {
+ value = trueOrd == docValues.ordValue();
+ }
+ }
+
+ @Override
+ public boolean getBoolean() {
+ return value;
+ }
+ @Override
+ public String getString() {
+ return exists ? Boolean.toString(value) : null;
+ }
+ @Override
+ public Object getObject() {
+ return exists ? value : null;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public void streamBooleans(BooleanConsumer cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ if (exists) {
+ cons.accept(Boolean.toString(value));
+ }
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+
+ @Override
+ public ExpressionComparator<Boolean> getObjectComparator(String expression) {
+ return new ExpressionComparator<>(expression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java
new file mode 100644
index 0000000..e4eecd3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java
@@ -0,0 +1,101 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.value.BooleanValueStream.CastingBooleanValueStream;
+import org.apache.solr.schema.BoolField;
+
+
+/**
+ * An analytics wrapper for a multi-valued {@link BoolField} with DocValues enabled.
+ */
+public class BooleanMultiField extends AnalyticsField implements CastingBooleanValueStream {
+ private SortedSetDocValues docValues;
+ private int count;
+ private boolean[] values;
+
+ private int trueOrd;
+
+ public BooleanMultiField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new boolean[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedSet(context.reader(), fieldName);
+
+ // figure out what ord maps to true
+ long numOrds = docValues.getValueCount();
+ // if no values in the segment, default trueOrd to something other then -1 (missing)
+ int trueOrd = -2;
+ for (int i=0; i<numOrds; i++) {
+ final BytesRef br = docValues.lookupOrd(i);
+ if (br.length==1 && br.bytes[br.offset]=='T') {
+ trueOrd = i;
+ break;
+ }
+ }
+
+ this.trueOrd = trueOrd;
+ }
+ @Override
+ public void collect(int doc) throws IOException {
+ count = 0;
+ if (docValues.advanceExact(doc)) {
+ int term;
+ while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+ if (count == values.length) {
+ resizeValues();
+ }
+ values[count++] = term == trueOrd;
+ }
+ }
+ }
+
+ private void resizeValues() {
+ boolean[] newValues = new boolean[values.length*2];
+ for (int i = 0; i < count; ++i) {
+ newValues[i] = values[i];
+ }
+ values = newValues;
+ }
+
+ @Override
+ public void streamBooleans(BooleanConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamBooleans(value -> cons.accept(Boolean.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamBooleans(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java
new file mode 100644
index 0000000..88e71bc
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java
@@ -0,0 +1,108 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.DateValue.CastingDateValue;
+import org.apache.solr.schema.DatePointField;
+import org.apache.solr.schema.TrieDateField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieDateField} or {@link DatePointField} with DocValues enabled.
+ */
+public class DateField extends AnalyticsField implements CastingDateValue {
+ private NumericDocValues docValues;
+ private long value;
+ private boolean exists;
+
+ public DateField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ exists = docValues.advanceExact(doc);
+ if (exists) {
+ value = docValues.longValue();
+ }
+ }
+
+ @Override
+ public long getLong() {
+ return value;
+ }
+ @Override
+ public Date getDate() {
+ return exists ? new Date(value) : null;
+ }
+ @Override
+ public String getString() {
+ return exists ? Instant.ofEpochMilli(value).toString() : null;
+ }
+ @Override
+ public Object getObject() {
+ return exists ? value : null;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+ @Override
+ public void streamDates(Consumer<Date> cons) {
+ if (exists) {
+ cons.accept(new Date(value));
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ if (exists) {
+ cons.accept(Instant.ofEpochMilli(value).toString());
+ }
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ if (exists) {
+ cons.accept(new Date(value));
+ }
+ }
+
+ @Override
+ public ExpressionComparator<Date> getObjectComparator(String expression) {
+ return new ExpressionComparator<>(expression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java
new file mode 100644
index 0000000..64ee489
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java
@@ -0,0 +1,47 @@
+/*
+ * 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.field;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.value.DateValueStream.CastingDateValueStream;
+import org.apache.solr.schema.TrieDateField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieDateField} with DocValues enabled.
+ */
+public class DateMultiField extends LongMultiField implements CastingDateValueStream {
+
+ public DateMultiField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void streamDates(Consumer<Date> cons) {
+ streamLongs(value -> cons.accept(new Date(value)));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamLongs(value -> cons.accept(Instant.ofEpochMilli(value).toString()));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamLongs(value -> cons.accept(new Date(value)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java
new file mode 100644
index 0000000..a1560ef
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java
@@ -0,0 +1,47 @@
+/*
+ * 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.field;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.value.DateValueStream.CastingDateValueStream;
+import org.apache.solr.schema.DatePointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link DatePointField} with DocValues enabled.
+ */
+public class DateMultiPointField extends LongMultiPointField implements CastingDateValueStream {
+
+ public DateMultiPointField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void streamDates(Consumer<Date> cons) {
+ streamLongs(value -> cons.accept(new Date(value)));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamLongs(value -> cons.accept(Instant.ofEpochMilli(value).toString()));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamLongs(value -> cons.accept(new Date(value)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java
new file mode 100644
index 0000000..68941a4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java
@@ -0,0 +1,97 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.DoubleValue.CastingDoubleValue;
+import org.apache.solr.schema.DoublePointField;
+import org.apache.solr.schema.TrieDoubleField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieDoubleField} or {@link DoublePointField} with DocValues enabled.
+ */
+public class DoubleField extends AnalyticsField implements CastingDoubleValue {
+ private NumericDocValues docValues;
+ private double value;
+ private boolean exists;
+
+ public DoubleField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ exists = docValues.advanceExact(doc);
+ if (exists) {
+ value = NumericUtils.sortableLongToDouble(docValues.longValue());
+ }
+ }
+
+ @Override
+ public double getDouble() {
+ return value;
+ }
+ @Override
+ public String getString() {
+ return exists ? Double.toString(value) : null;
+ }
+ @Override
+ public Object getObject() {
+ return exists ? value : null;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ if (exists) {
+ cons.accept(Double.toString(value));
+ }
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+
+ @Override
+ public ExpressionComparator<Double> getObjectComparator(String expression) {
+ return new ExpressionComparator<>(expression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java
new file mode 100644
index 0000000..3d58634
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java
@@ -0,0 +1,85 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.value.DoubleValueStream.CastingDoubleValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieDoubleField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieDoubleField} with DocValues enabled.
+ */
+public class DoubleMultiField extends AnalyticsField implements CastingDoubleValueStream {
+ private SortedSetDocValues docValues;
+ private int count;
+ private double[] values;
+
+ public DoubleMultiField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new double[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedSet(context.reader(), fieldName);
+ }
+ @Override
+ public void collect(int doc) throws IOException {
+ count = 0;
+ if (docValues.advanceExact(doc)) {
+ int term;
+ while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+ if (count == values.length) {
+ resizeValues();
+ }
+ values[count++] = NumericUtils.sortableLongToDouble(LegacyNumericUtils.prefixCodedToLong(docValues.lookupOrd(term)));
+ }
+ }
+ }
+
+ private void resizeValues() {
+ double[] newValues = new double[values.length*2];
+ for (int i = 0; i < count; ++i) {
+ newValues[i] = values[i];
+ }
+ values = newValues;
+ }
+
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamDoubles(value -> cons.accept(Double.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamDoubles(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java
new file mode 100644
index 0000000..0933f60
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java
@@ -0,0 +1,81 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.value.DoubleValueStream.CastingDoubleValueStream;
+import org.apache.solr.schema.DoublePointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link DoublePointField} with DocValues enabled.
+ */
+public class DoubleMultiPointField extends AnalyticsField implements CastingDoubleValueStream {
+ private SortedNumericDocValues docValues;
+ private int count;
+ private double[] values;
+
+ public DoubleMultiPointField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new double[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+ }
+ @Override
+ public void collect(int doc) throws IOException {
+ if (docValues.advanceExact(doc)) {
+ count = docValues.docValueCount();
+ resizeEmptyValues(count);
+ for (int i = 0; i < count; ++i) {
+ values[i] = NumericUtils.sortableLongToDouble(docValues.nextValue());
+ }
+ } else {
+ count = 0;
+ }
+ }
+
+ private void resizeEmptyValues(int count) {
+ if (count > values.length) {
+ values = new double[count];
+ }
+ }
+
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamDoubles(value -> cons.accept(Double.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamDoubles(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java
new file mode 100644
index 0000000..c382d61
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java
@@ -0,0 +1,108 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.FloatValue.CastingFloatValue;
+import org.apache.solr.schema.FloatPointField;
+import org.apache.solr.schema.TrieFloatField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieFloatField} or {@link FloatPointField} with DocValues enabled.
+ */
+public class FloatField extends AnalyticsField implements CastingFloatValue {
+ private NumericDocValues docValues;
+ private float value;
+ private boolean exists;
+
+ public FloatField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ exists = docValues.advanceExact(doc);
+ if (exists) {
+ value = NumericUtils.sortableIntToFloat((int)docValues.longValue());
+ }
+ }
+
+ @Override
+ public float getFloat() {
+ return value;
+ }
+ @Override
+ public double getDouble() {
+ return (double)value;
+ }
+ @Override
+ public String getString() {
+ return exists ? Float.toString(value) : null;
+ }
+ @Override
+ public Object getObject() {
+ return exists ? value : null;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public void streamFloats(FloatConsumer cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ if (exists) {
+ cons.accept((double)value);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ if (exists) {
+ cons.accept(Float.toString(value));
+ }
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+
+ @Override
+ public ExpressionComparator<Float> getObjectComparator(String expression) {
+ return new ExpressionComparator<>(expression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java
new file mode 100644
index 0000000..acfce18
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java
@@ -0,0 +1,91 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.FloatValueStream.CastingFloatValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieFloatField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieFloatField} with DocValues enabled.
+ */
+public class FloatMultiField extends AnalyticsField implements CastingFloatValueStream {
+ private SortedSetDocValues docValues;
+ private int count;
+ private float[] values;
+
+ public FloatMultiField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new float[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedSet(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ count = 0;
+ if (docValues.advanceExact(doc)) {
+ int term;
+ while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+ if (count == values.length) {
+ resizeValues();
+ }
+ values[count++] = NumericUtils.sortableIntToFloat(LegacyNumericUtils.prefixCodedToInt(docValues.lookupOrd(term)));
+ }
+ }
+ }
+
+ private void resizeValues() {
+ float[] newValues = new float[values.length*2];
+ for (int i = 0; i < count; ++i) {
+ newValues[i] = values[i];
+ }
+ values = newValues;
+ }
+
+ @Override
+ public void streamFloats(FloatConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ streamFloats(value -> cons.accept((double)value));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamFloats(value -> cons.accept(Float.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamFloats(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.java
new file mode 100644
index 0000000..947035e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.FloatValueStream.CastingFloatValueStream;
+import org.apache.solr.schema.FloatPointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link FloatPointField} with DocValues enabled.
+ */
+public class FloatMultiPointField extends AnalyticsField implements CastingFloatValueStream {
+ private SortedNumericDocValues docValues;
+ private int count;
+ private float[] values;
+
+ public FloatMultiPointField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new float[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ if (docValues.advanceExact(doc)) {
+ count = docValues.docValueCount();
+ resizeEmptyValues(count);
+ for (int i = 0; i < count; ++i) {
+ values[i] = NumericUtils.sortableIntToFloat((int)docValues.nextValue());
+ }
+ } else {
+ count = 0;
+ }
+ }
+
+ private void resizeEmptyValues(int count) {
+ if (count > values.length) {
+ values = new float[count];
+ }
+ }
+
+ @Override
+ public void streamFloats(FloatConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ streamFloats(value -> cons.accept((double)value));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamFloats(value -> cons.accept(Float.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamFloats(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java
new file mode 100644
index 0000000..e9ae52b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java
@@ -0,0 +1,129 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.IntValue.CastingIntValue;
+import org.apache.solr.schema.IntPointField;
+import org.apache.solr.schema.TrieIntField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieIntField} or {@link IntPointField} with DocValues enabled.
+ */
+public class IntField extends AnalyticsField implements CastingIntValue {
+ private NumericDocValues docValues;
+ private int value;
+ private boolean exists;
+
+ public IntField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ exists = docValues.advanceExact(doc);
+ if (exists) {
+ value = (int)docValues.longValue();
+ }
+ }
+
+ @Override
+ public int getInt() {
+ return value;
+ }
+ @Override
+ public long getLong() {
+ return (long)value;
+ }
+ @Override
+ public float getFloat() {
+ return (float)value;
+ }
+ @Override
+ public double getDouble() {
+ return (double)value;
+ }
+ @Override
+ public String getString() {
+ return exists ? Integer.toString(value) : null;
+ }
+ @Override
+ public Object getObject() {
+ return exists ? value : null;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public void streamInts(IntConsumer cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ if (exists) {
+ cons.accept((long)value);
+ }
+ }
+ @Override
+ public void streamFloats(FloatConsumer cons) {
+ if (exists) {
+ cons.accept((float)value);
+ }
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ if (exists) {
+ cons.accept((double)value);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ if (exists) {
+ cons.accept(Integer.toString(value));
+ }
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+
+ @Override
+ public ExpressionComparator<Integer> getObjectComparator(String expression) {
+ return new ExpressionComparator<>(expression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java
new file mode 100644
index 0000000..657b1f3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java
@@ -0,0 +1,100 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.IntValueStream.CastingIntValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieIntField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieIntField} with DocValues enabled.
+ */
+public class IntMultiField extends AnalyticsField implements CastingIntValueStream {
+ private SortedSetDocValues docValues;
+ private int count;
+ private int[] values;
+
+ public IntMultiField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new int[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedSet(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ count = 0;
+ if (docValues.advanceExact(doc)) {
+ int term;
+ while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+ if (count == values.length) {
+ resizeValues();
+ }
+ values[count++] = LegacyNumericUtils.prefixCodedToInt(docValues.lookupOrd(term));
+ }
+ }
+ }
+
+ private void resizeValues() {
+ int[] newValues = new int[values.length*2];
+ for (int i = 0; i < count; ++i) {
+ newValues[i] = values[i];
+ }
+ values = newValues;
+ }
+
+ @Override
+ public void streamInts(IntConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ streamInts(value -> cons.accept((long)value));
+ }
+ @Override
+ public void streamFloats(FloatConsumer cons) {
+ streamInts(value -> cons.accept((float)value));
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ streamInts(value -> cons.accept((double)value));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamInts(value -> cons.accept(Integer.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamInts(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java
new file mode 100644
index 0000000..2608fa1
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java
@@ -0,0 +1,96 @@
+/*
+ * 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.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.IntValueStream.CastingIntValueStream;
+import org.apache.solr.schema.IntPointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link IntPointField} with DocValues enabled.
+ */
+public class IntMultiPointField extends AnalyticsField implements CastingIntValueStream {
+ private SortedNumericDocValues docValues;
+ private int count;
+ private int[] values;
+
+ public IntMultiPointField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new int[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ if (docValues.advanceExact(doc)) {
+ count = docValues.docValueCount();
+ resizeEmptyValues(count);
+ for (int i = 0; i < count; ++i) {
+ values[i] = (int)docValues.nextValue();
+ }
+ } else {
+ count = 0;
+ }
+ }
+
+ private void resizeEmptyValues(int count) {
+ if (count > values.length) {
+ values = new int[count];
+ }
+ }
+
+ @Override
+ public void streamInts(IntConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ streamInts(value -> cons.accept((long)value));
+ }
+ @Override
+ public void streamFloats(FloatConsumer cons) {
+ streamInts(value -> cons.accept((float)value));
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ streamInts(value -> cons.accept((double)value));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamInts(value -> cons.accept(Integer.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamInts(value -> cons.accept(value));
+ }
+}