diff --git a/CHANGES.txt b/CHANGES.txt
index 0486929cade..778afd70a2e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -98,6 +98,8 @@ New Features
7. SOLR-680: Add StatsComponent. This gets simple statistics on matched numeric fields,
including: min, max, mean, median, stddev. (koji, ryan)
+ 7.1 SOLR-1380: Added support for multi-valued fields (Harish Agarwal via gsingers)
+
8. SOLR-561: Added Replication implemented in Java as a request handler. Supports index replication
as well as configuration replication and exposes detailed statistics and progress information
on the Admin page. Works on all platforms. (Noble Paul, yonik, Akshay Ukey, shalin)
diff --git a/src/java/org/apache/solr/handler/component/FieldFacetStats.java b/src/java/org/apache/solr/handler/component/FieldFacetStats.java
new file mode 100644
index 00000000000..f385a09b9ea
--- /dev/null
+++ b/src/java/org/apache/solr/handler/component/FieldFacetStats.java
@@ -0,0 +1,144 @@
+package org.apache.solr.handler.component;
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.FieldCache;
+import org.apache.solr.schema.FieldType;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 9/10/2009 - Moved out of StatsComponent to allow open access to UnInvertedField
+ * FieldFacetStats is a utility to accumulate statistics on a set of values in one field,
+ * for facet values present in another field.
+ *
+ * @see org.apache.solr.handler.component.StatsComponent
+ *
+ */
+
+public class FieldFacetStats {
+ public final String name;
+ final FieldCache.StringIndex si;
+ final FieldType ft;
+
+ final String[] terms;
+ final int[] termNum;
+
+ final int startTermIndex;
+ final int endTermIndex;
+ final int nTerms;
+
+ final int numStatsTerms;
+
+ public final Map facetStatsValues;
+
+ final List> facetStatsTerms;
+
+ public FieldFacetStats(String name, FieldCache.StringIndex si, FieldType ft, int numStatsTerms) {
+ this.name = name;
+ this.si = si;
+ this.ft = ft;
+ this.numStatsTerms = numStatsTerms;
+
+ terms = si.lookup;
+ termNum = si.order;
+ startTermIndex = 1;
+ endTermIndex = terms.length;
+ nTerms = endTermIndex - startTermIndex;
+
+ facetStatsValues = new HashMap();
+
+ // for mv stats field, we'll want to keep track of terms
+ facetStatsTerms = new ArrayList>();
+ if (numStatsTerms == 0) return;
+ int i = 0;
+ for (; i < numStatsTerms; i++) {
+ facetStatsTerms.add(new HashMap());
+ }
+ }
+
+ String getTermText(int docID) {
+ return terms[termNum[docID]];
+ }
+
+
+ public boolean facet(int docID, Double v) {
+ if (v == null) return false;
+
+ int term = termNum[docID];
+ int arrIdx = term - startTermIndex;
+ if (arrIdx >= 0 && arrIdx < nTerms) {
+ String key = ft.indexedToReadable(terms[term]);
+ StatsValues stats = facetStatsValues.get(key);
+ if (stats == null) {
+ stats = new StatsValues();
+ facetStatsValues.put(key, stats);
+ }
+ stats.accumulate(v);
+ return true;
+ }
+ return false;
+ }
+
+
+ //function to keep track of facet counts for term number
+ public boolean facetTermNum(int docID, int statsTermNum) {
+
+ int term = termNum[docID];
+ int arrIdx = term - startTermIndex;
+ if (arrIdx >= 0 && arrIdx < nTerms) {
+ String key = ft.indexedToReadable(terms[term]);
+ HashMap statsTermCounts = facetStatsTerms.get(statsTermNum);
+ Integer statsTermCount = statsTermCounts.get(key);
+ if (statsTermCount == null) {
+ statsTermCounts.put(key, 1);
+ } else {
+ statsTermCounts.put(key, statsTermCount + 1);
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ //function to accumulate counts for statsTermNum to specified value
+ public boolean accumulateTermNum(int statsTermNum, Double value) {
+ if (value == null) return false;
+ for (Map.Entry stringIntegerEntry : facetStatsTerms.get(statsTermNum).entrySet()) {
+ Map.Entry pairs = (Map.Entry) stringIntegerEntry;
+ String key = (String) pairs.getKey();
+ StatsValues facetStats = facetStatsValues.get(key);
+ if (facetStats == null) {
+ facetStats = new StatsValues();
+ facetStatsValues.put(key, facetStats);
+ }
+ Integer count = (Integer) pairs.getValue();
+ if (count != null) {
+ facetStats.accumulate(value, count);
+ }
+ }
+ return true;
+ }
+
+}
+
+
diff --git a/src/java/org/apache/solr/handler/component/StatsComponent.java b/src/java/org/apache/solr/handler/component/StatsComponent.java
index 8d0c74a33a7..3ce47feb1d0 100644
--- a/src/java/org/apache/solr/handler/component/StatsComponent.java
+++ b/src/java/org/apache/solr/handler/component/StatsComponent.java
@@ -28,11 +28,16 @@ import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.params.StatsParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.handler.component.StatsValues;
+import org.apache.solr.handler.component.FieldFacetStats;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.request.UnInvertedField;
+import org.apache.solr.core.SolrCore;
/**
* Stats component calculates simple statistics on numeric field values
@@ -173,166 +178,6 @@ class StatsInfo {
}
}
-class StatsValues {
- private static final String FACETS = "facets";
- double min;
- double max;
- double sum;
- double sumOfSquares;
- long count;
- long missing;
-
- // facetField facetValue
- Map> facets;
-
- public StatsValues() {
- reset();
- }
-
- public void accumulate(NamedList stv){
- min = Math.min(min, (Double)stv.get("min"));
- max = Math.max(max, (Double)stv.get("max"));
- sum += (Double)stv.get("sum");
- count += (Long)stv.get("count");
- missing += (Long)stv.get("missing");
- sumOfSquares += (Double)stv.get("sumOfSquares");
-
- NamedList f = (NamedList)stv.get( FACETS );
- if( f != null ) {
- if( facets == null ) {
- facets = new HashMap>();
- }
-
- for( int i=0; i< f.size(); i++ ) {
- String field = f.getName(i);
- NamedList vals = (NamedList)f.getVal( i );
- Map addTo = facets.get( field );
- if( addTo == null ) {
- addTo = new HashMap();
- facets.put( field, addTo );
- }
- for( int j=0; j< vals.size(); j++ ) {
- String val = f.getName(i);
- StatsValues vvals = addTo.get( val );
- if( vvals == null ) {
- vvals = new StatsValues();
- addTo.put( val, vvals );
- }
- vvals.accumulate( (NamedList)f.getVal( i ) );
- }
- }
- }
- }
-
- public void accumulate(double v){
- sumOfSquares += (v*v); // for std deviation
- min = Math.min(min, v);
- max = Math.max(max, v);
- sum += v;
- count++;
- }
-
- public double getAverage(){
- return sum / count;
- }
-
- public double getStandardDeviation()
- {
- if( count <= 1.0D )
- return 0.0D;
-
- return Math.sqrt( ( ( count * sumOfSquares ) - ( sum * sum ) )
- / ( count * ( count - 1.0D ) ) );
- }
-
- public void reset(){
- min = Double.MAX_VALUE;
- max = Double.NEGATIVE_INFINITY;
- sum = count = missing = 0;
- sumOfSquares = 0;
- facets = null;
- }
-
- public NamedList> getStatsValues(){
- NamedList