You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by yo...@apache.org on 2015/03/16 06:48:15 UTC

svn commit: r1666876 - in /lucene/dev/branches/branch_5x: ./ solr/ solr/contrib/ solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/ solr/core/ solr/core/src/java/org/apache/solr/handler/ solr/core/src/java/org/apache/solr/handl...

Author: yonik
Date: Mon Mar 16 05:48:14 2015
New Revision: 1666876

URL: http://svn.apache.org/r1666876
Log:
SOLR-7214: JSON Facet API

Added:
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/json/
      - copied from r1666856, lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/json/
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/macro/
      - copied from r1666856, lucene/dev/trunk/solr/core/src/java/org/apache/solr/request/macro/
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/QueryContext.java
      - copied unchanged from r1666856, lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QueryContext.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/facet/
      - copied from r1666856, lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/facet/
    lucene/dev/branches/branch_5x/solr/core/src/test-files/solr/collection1/conf/schema_latest.xml
      - copied unchanged from r1666856, lucene/dev/trunk/solr/core/src/test-files/solr/collection1/conf/schema_latest.xml
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/search/facet/
      - copied from r1666856, lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/facet/
    lucene/dev/branches/branch_5x/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
      - copied unchanged from r1666856, lucene/dev/trunk/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
Removed:
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/UnInvertedField.java
Modified:
    lucene/dev/branches/branch_5x/   (props changed)
    lucene/dev/branches/branch_5x/solr/   (props changed)
    lucene/dev/branches/branch_5x/solr/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_5x/solr/contrib/   (props changed)
    lucene/dev/branches/branch_5x/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java
    lucene/dev/branches/branch_5x/solr/core/   (props changed)
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSet.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSetBase.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/FunctionQParser.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/QueryParsing.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
    lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
    lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java
    lucene/dev/branches/branch_5x/solr/solrj/   (props changed)
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/ModifiableSolrParams.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/MultiMapSolrParams.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java
    lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/SimpleOrderedMap.java
    lucene/dev/branches/branch_5x/solr/test-framework/   (props changed)

Modified: lucene/dev/branches/branch_5x/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/CHANGES.txt?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/CHANGES.txt (original)
+++ lucene/dev/branches/branch_5x/solr/CHANGES.txt Mon Mar 16 05:48:14 2015
@@ -117,6 +117,15 @@ New Features
 * SOLR-7218: lucene/solr query syntax to give any query clause a constant score.
   General Form: <clause>^=<constant_score>
   Example: (color:blue color:green)^=2.0 text:shoes
+  (yonik)
+
+* SOLR-7214: New Facet module with a JSON API, facet functions, aggregations, and analytics.
+  Any facet type can have sub facets, and facets can be sorted by arbitrary aggregation functions.
+  Examples:
+    json.facet={x:'avg(price)', y:'unique(color)'}
+    json.facet={count1:{query:"price:[10 TO 20]"}, count2:{query:"color:blue AND popularity:[0 TO 50]"} }
+    json.facet={categories:{terms:{field:cat, sort:"x desc", facet:{x:"avg(price)", y:"sum(price)"}}}}
+  (yonik)
 
 
 Bug Fixes

Modified: lucene/dev/branches/branch_5x/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java (original)
+++ lucene/dev/branches/branch_5x/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/DataImportHandler.java Mon Mar 16 05:48:14 2015
@@ -21,6 +21,7 @@ import static org.apache.solr.handler.da
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.params.UpdateParams;
@@ -84,11 +85,14 @@ public class DataImportHandler extends R
   public DataImporter getImporter() {
     return this.importer;
   }
-  
+
   @Override
   @SuppressWarnings("unchecked")
   public void init(NamedList args) {
     super.init(args);
+    Map<String,String> macro = new HashMap<>();
+    macro.put("expandMacros", "false");
+    defaults = SolrParams.wrapDefaults(defaults, new MapSolrParams(macro));
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java Mon Mar 16 05:48:14 2015
@@ -25,6 +25,7 @@ import org.apache.solr.core.PluginInfo;
 import org.apache.solr.core.PluginBag;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.handler.component.SearchHandler;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.response.SolrQueryResponse;
@@ -136,7 +137,7 @@ public abstract class RequestHandlerBase
     TimerContext timer = requestTimes.time();
     try {
       if(pluginInfo != null && pluginInfo.attributes.containsKey(USEPARAM)) req.getContext().put(USEPARAM,pluginInfo.attributes.get(USEPARAM));
-      SolrPluginUtils.setDefaults(req,defaults,appends,invariants);
+      SolrPluginUtils.setDefaults(this, req, defaults, appends, invariants);
       req.getContext().remove(USEPARAM);
       rsp.setHttpCaching(httpCaching);
       handleRequestBody( req, rsp );

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchComponent.java Mon Mar 16 05:48:14 2015
@@ -25,6 +25,7 @@ import java.util.Map;
 
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.SolrInfoMBean;
+import org.apache.solr.search.facet.FacetModule;
 import org.apache.solr.util.plugin.NamedListInitializedPlugin;
 
 /**
@@ -134,6 +135,7 @@ public abstract class SearchComponent im
     map.put(HighlightComponent.COMPONENT_NAME, HighlightComponent.class);
     map.put(QueryComponent.COMPONENT_NAME, QueryComponent.class);
     map.put(FacetComponent.COMPONENT_NAME, FacetComponent.class);
+    map.put(FacetModule.COMPONENT_NAME, FacetModule.class);
     map.put(MoreLikeThisComponent.COMPONENT_NAME, MoreLikeThisComponent.class);
     map.put(StatsComponent.COMPONENT_NAME, StatsComponent.class);
     map.put(DebugComponent.COMPONENT_NAME, DebugComponent.class);

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java Mon Mar 16 05:48:14 2015
@@ -35,6 +35,7 @@ import org.apache.solr.handler.RequestHa
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.search.SolrQueryTimeoutImpl;
+import org.apache.solr.search.facet.FacetModule;
 import org.apache.solr.util.RTimer;
 import org.apache.solr.util.SolrPluginUtils;
 import org.apache.solr.util.plugin.PluginInfoInitialized;
@@ -75,6 +76,7 @@ public class SearchHandler extends Reque
     ArrayList<String> names = new ArrayList<>(6);
     names.add( QueryComponent.COMPONENT_NAME );
     names.add( FacetComponent.COMPONENT_NAME );
+    names.add( FacetModule.COMPONENT_NAME );
     names.add( MoreLikeThisComponent.COMPONENT_NAME );
     names.add( HighlightComponent.COMPONENT_NAME );
     names.add( StatsComponent.COMPONENT_NAME );

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java Mon Mar 16 05:48:14 2015
@@ -97,6 +97,13 @@ public interface SolrQueryRequest {
    * @param params The new set of parameter
    */
   public void forward(String handler, SolrParams params,  SolrQueryResponse rsp);
+
+  /** Returns any associated JSON (or null if none) in deserialized generic form.
+   * Java classes used to represent the JSON are as follows: Map, List, String, Long, Double, Boolean
+   */
+  public Map<String,Object> getJSON();
+
+  public void setJSON(Map<String,Object> json);
 }
 
 

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java Mon Mar 16 05:48:14 2015
@@ -50,6 +50,7 @@ public abstract class SolrQueryRequestBa
   protected SolrParams params;
   protected Map<Object,Object> context;
   protected Iterable<ContentStream> streams;
+  protected Map<String,Object> json;
 
   private final RTimer requestTimer;
 
@@ -172,4 +173,14 @@ public abstract class SolrQueryRequestBa
 
   }
 
+  @Override
+  public Map<String, Object> getJSON() {
+    return json;
+  }
+
+  @Override
+  public void setJSON(Map<String, Object> json) {
+    this.json = json;
+  }
+
 }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSet.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSet.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSet.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSet.java Mon Mar 16 05:48:14 2015
@@ -17,6 +17,8 @@
 
 package org.apache.solr.search;
 
+import java.io.Closeable;
+
 import org.apache.lucene.search.Filter;
 import org.apache.solr.common.SolrException;
 
@@ -30,7 +32,7 @@ import org.apache.solr.common.SolrExcept
  *
  * @since solr 0.9
  */
-public interface DocSet /* extends Collection<Integer> */ {
+public interface DocSet extends Closeable /* extends Collection<Integer> */ {
   
   /**
    * Adds the specified document if it is not currently in the DocSet

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSetBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSetBase.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSetBase.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/DocSetBase.java Mon Mar 16 05:48:14 2015
@@ -17,6 +17,8 @@
 
 package org.apache.solr.search;
 
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.BitsFilteredDocIdSet;
@@ -244,4 +246,9 @@ abstract class DocSetBase implements Doc
     }
   }
 
+
+  /** FUTURE: for off-heap */
+  @Override
+  public void close() throws IOException {
+  }
 }

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/FunctionQParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/FunctionQParser.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/FunctionQParser.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/FunctionQParser.java Mon Mar 16 05:48:14 2015
@@ -23,6 +23,7 @@ import org.apache.lucene.search.Query;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.search.facet.AggValueSource;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -30,6 +31,10 @@ import java.util.List;
 
 public class FunctionQParser extends QParser {
 
+  public static final int FLAG_CONSUME_DELIMITER = 0x01;  // consume delimiter after parsing arg
+  public static final int FLAG_IS_AGG = 0x02;
+  public static final int FLAG_DEFAULT = FLAG_CONSUME_DELIMITER;
+
   /** @lucene.internal */
   public QueryParsing.StrParser sp;
   boolean parseMultipleSources = true;
@@ -37,6 +42,15 @@ public class FunctionQParser extends QPa
 
   public FunctionQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
     super(qstr, localParams, params, req);
+    setString(qstr);
+  }
+
+  @Override
+  public void setString(String s) {
+    super.setString(s);
+    if (s != null) {
+      sp = new QueryParsing.StrParser( s );
+    }
   }
 
   public void setParseMultipleSources(boolean parseMultipleSources) {
@@ -59,13 +73,11 @@ public class FunctionQParser extends QPa
 
   @Override
   public Query parse() throws SyntaxError {
-    sp = new QueryParsing.StrParser(getString());
-
     ValueSource vs = null;
     List<ValueSource> lst = null;
 
     for(;;) {
-      ValueSource valsource = parseValueSource(false);
+      ValueSource valsource = parseValueSource(FLAG_DEFAULT & ~FLAG_CONSUME_DELIMITER);
       sp.eatws();
       if (!parseMultipleSources) {
         vs = valsource; 
@@ -210,7 +222,7 @@ public class FunctionQParser extends QPa
   public List<ValueSource> parseValueSourceList() throws SyntaxError {
     List<ValueSource> sources = new ArrayList<>(3);
     while (hasMoreArguments()) {
-      sources.add(parseValueSource(true));
+      sources.add(parseValueSource(FLAG_DEFAULT | FLAG_CONSUME_DELIMITER));
     }
     return sources;
   }
@@ -220,7 +232,7 @@ public class FunctionQParser extends QPa
    */
   public ValueSource parseValueSource() throws SyntaxError {
     /* consume the delimiter afterward for an external call to parseValueSource */
-    return parseValueSource(true);
+    return parseValueSource(FLAG_DEFAULT | FLAG_CONSUME_DELIMITER);
   }
   
   /*
@@ -274,7 +286,11 @@ public class FunctionQParser extends QPa
    * 
    * @param doConsumeDelimiter whether to consume a delimiter following the ValueSource  
    */
-  protected ValueSource parseValueSource(boolean doConsumeDelimiter) throws SyntaxError {
+   protected ValueSource parseValueSource(boolean doConsumeDelimiter) throws SyntaxError {
+     return parseValueSource( doConsumeDelimiter ? (FLAG_DEFAULT | FLAG_CONSUME_DELIMITER) : (FLAG_DEFAULT & ~FLAG_CONSUME_DELIMITER) );
+   }
+
+   protected ValueSource parseValueSource(int flags) throws SyntaxError {
     ValueSource valueSource;
     
     int ch = sp.peek();
@@ -365,12 +381,57 @@ public class FunctionQParser extends QPa
 
     }
     
-    if (doConsumeDelimiter)
+    if ((flags & FLAG_CONSUME_DELIMITER) != 0) {
       consumeArgumentDelimiter();
+    }
     
     return valueSource;
   }
 
+  /** @lucene.experimental */
+  public AggValueSource parseAgg(int flags) throws SyntaxError {
+    String id = sp.getId();
+    AggValueSource vs = null;
+    boolean hasParen = false;
+
+    if ("agg".equals(id)) {
+      hasParen = sp.opt("(");
+      vs = parseAgg(flags | FLAG_IS_AGG);
+    } else {
+      // parse as an aggregation...
+      if (!id.startsWith("agg_")) {
+        id = "agg_" + id;
+      }
+
+      hasParen = sp.opt("(");
+
+      ValueSourceParser argParser = req.getCore().getValueSourceParser(id);
+      argParser = req.getCore().getValueSourceParser(id);
+      if (argParser == null) {
+        throw new SyntaxError("Unknown aggregation " + id + " in (" + sp + ")");
+      }
+
+      ValueSource vv = argParser.parse(this);
+      if (!(vv instanceof AggValueSource)) {
+        if (argParser == null) {
+          throw new SyntaxError("Expected aggregation from " + id + " but got (" + vv + ") in (" + sp + ")");
+        }
+      }
+      vs = (AggValueSource) vv;
+    }
+
+    if (hasParen) {
+      sp.expect(")");
+    }
+
+    if ((flags & FLAG_CONSUME_DELIMITER) != 0) {
+      consumeArgumentDelimiter();
+    }
+
+    return vs;
+  }
+
+
   /**
    * Consume an argument delimiter (a comma) from the token stream.
    * Only consumes if more arguments should exist (no ending parens or end of string).

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/QueryParsing.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/QueryParsing.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/QueryParsing.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/QueryParsing.java Mon Mar 16 05:48:14 2015
@@ -593,9 +593,9 @@ public class QueryParsing {
    * <b>Note: This API is experimental and may change in non backward-compatible ways in the future</b>
    */
   public static class StrParser {
-    String val;
-    int pos;
-    int end;
+    public String val;
+    public int pos;
+    public int end;
 
     public StrParser(String val) {
       this(val, 0, val.length());
@@ -607,19 +607,19 @@ public class QueryParsing {
       this.end = end;
     }
 
-    void eatws() {
+    public void eatws() {
       while (pos < end && Character.isWhitespace(val.charAt(pos))) pos++;
     }
 
-    char ch() {
+    public char ch() {
       return pos < end ? val.charAt(pos) : 0;
     }
 
-    void skip(int nChars) {
+    public void skip(int nChars) {
       pos = Math.max(pos + nChars, end);
     }
 
-    boolean opt(String s) {
+    public boolean opt(String s) {
       eatws();
       int slen = s.length();
       if (val.regionMatches(pos, s, 0, slen)) {
@@ -629,7 +629,7 @@ public class QueryParsing {
       return false;
     }
 
-    boolean opt(char ch) {
+    public boolean opt(char ch) {
       eatws();
       if (pos < end && val.charAt(pos) == ch) {
         pos++;
@@ -639,7 +639,7 @@ public class QueryParsing {
     }
 
 
-    void expect(String s) throws SyntaxError {
+    public void expect(String s) throws SyntaxError {
       eatws();
       int slen = s.length();
       if (val.regionMatches(pos, s, 0, slen)) {
@@ -649,7 +649,7 @@ public class QueryParsing {
       }
     }
 
-    float getFloat() {
+    public float getFloat() {
       eatws();
       char[] arr = new char[end - pos];
       int i;
@@ -669,7 +669,7 @@ public class QueryParsing {
       return Float.parseFloat(new String(arr, 0, i));
     }
 
-    Number getNumber() {
+    public Number getNumber() {
       eatws();
       int start = pos;
       boolean flt = false;
@@ -694,7 +694,7 @@ public class QueryParsing {
       }
     }
 
-    double getDouble() {
+    public double getDouble() {
       eatws();
       char[] arr = new char[end - pos];
       int i;
@@ -714,7 +714,7 @@ public class QueryParsing {
       return Double.parseDouble(new String(arr, 0, i));
     }
 
-    int getInt() {
+    public int getInt() {
       eatws();
       char[] arr = new char[end - pos];
       int i;
@@ -734,11 +734,11 @@ public class QueryParsing {
     }
 
 
-    String getId() throws SyntaxError {
+    public String getId() throws SyntaxError {
       return getId("Expected identifier");
     }
 
-    String getId(String errMessage) throws SyntaxError {
+    public String getId(String errMessage) throws SyntaxError {
       eatws();
       int id_start = pos;
       char ch;
@@ -787,7 +787,7 @@ public class QueryParsing {
      * Skips leading whitespace and returns whatever sequence of non 
      * whitespace it can find (or hte empty string)
      */
-    String getSimpleString() {
+    public String getSimpleString() {
       eatws();
       int startPos = pos;
       char ch;
@@ -804,7 +804,7 @@ public class QueryParsing {
      * sort direction. (True is desc, False is asc).  
      * Position is advanced to after the comma (or end) when result is non null 
      */
-    Boolean getSortDirection() throws SyntaxError {
+    public Boolean getSortDirection() throws SyntaxError {
       final int startPos = pos;
       final String order = getId(null);
 
@@ -835,7 +835,7 @@ public class QueryParsing {
     }
 
     // return null if not a string
-    String getQuotedString() throws SyntaxError {
+    public String getQuotedString() throws SyntaxError {
       eatws();
       char delim = peekChar();
       if (!(delim == '\"' || delim == '\'')) {
@@ -888,13 +888,13 @@ public class QueryParsing {
     }
 
     // next non-whitespace char
-    char peek() {
+    public char peek() {
       eatws();
       return pos < end ? val.charAt(pos) : 0;
     }
 
     // next char
-    char peekChar() {
+    public char peekChar() {
       return pos < end ? val.charAt(pos) : 0;
     }
 

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java Mon Mar 16 05:48:14 2015
@@ -79,7 +79,7 @@ import org.apache.solr.core.SolrInfoMBea
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.request.UnInvertedField;
+import org.apache.solr.search.facet.UnInvertedField;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
@@ -774,7 +774,7 @@ public class SolrIndexSearcher extends I
   ////////////////////////////////////////////////////////////////////////////////
 
   /** expert: internal API, subject to change */
-  public SolrCache<String,UnInvertedField> getFieldValueCache() {
+  public SolrCache<String, org.apache.solr.search.facet.UnInvertedField> getFieldValueCache() {
     return fieldValueCache;
   }
 

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/SolrReturnFields.java Mon Mar 16 05:48:14 2015
@@ -151,7 +151,7 @@ public class SolrReturnFields extends Re
   }
 
   // like getId, but also accepts dashes for legacy fields
-  String getFieldName(QueryParsing.StrParser sp) {
+  public static String getFieldName(QueryParsing.StrParser sp) {
     sp.eatws();
     int id_start = sp.pos;
     char ch;

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java Mon Mar 16 05:48:14 2015
@@ -40,6 +40,14 @@ import org.apache.solr.common.SolrExcept
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.schema.*;
+import org.apache.solr.search.facet.AggValueSource;
+import org.apache.solr.search.facet.AvgAgg;
+import org.apache.solr.search.facet.CountAgg;
+import org.apache.solr.search.facet.MaxAgg;
+import org.apache.solr.search.facet.MinAgg;
+import org.apache.solr.search.facet.SumAgg;
+import org.apache.solr.search.facet.SumsqAgg;
+import org.apache.solr.search.facet.UniqueAgg;
 import org.apache.solr.search.function.CollapseScoreFunction;
 import org.apache.solr.search.function.OrdFieldSource;
 import org.apache.solr.search.function.ReverseOrdFieldSource;
@@ -787,8 +795,88 @@ public abstract class ValueSourceParser
       }
     });
 
+
+    addParser("agg", new ValueSourceParser() {
+      @Override
+      public AggValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return fp.parseAgg(FunctionQParser.FLAG_DEFAULT);
+      }
+    });
+
+    addParser("agg_count", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return new CountAgg();
+      }
+    });
+
+    addParser("agg_unique", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return new UniqueAgg(fp.parseArg());
+      }
+    });
+
+    addParser("agg_sum", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return new SumAgg(fp.parseValueSource());
+      }
+    });
+
+    addParser("agg_avg", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return new AvgAgg(fp.parseValueSource());
+      }
+    });
+
+    addParser("agg_sumsq", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return new SumsqAgg(fp.parseValueSource());
+      }
+    });
+
+    /***
+     addParser("agg_stdev", new ValueSourceParser() {
+    @Override
+    public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+    return null;
+    }
+    });
+
+     addParser("agg_multistat", new ValueSourceParser() {
+    @Override
+    public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+    return null;
+    }
+    });
+     ***/
+
+    addParser("agg_min", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return new MinAgg(fp.parseValueSource());
+      }
+    });
+
+    addParser("agg_max", new ValueSourceParser() {
+      @Override
+      public ValueSource parse(FunctionQParser fp) throws SyntaxError {
+        return new MaxAgg(fp.parseValueSource());
+      }
+    });
+
+
+
   }
 
+  ///////////////////////////////////////////////////////////////////////////////
+  ///////////////////////////////////////////////////////////////////////////////
+  ///////////////////////////////////////////////////////////////////////////////
+
+
   private static TInfo parseTerm(FunctionQParser fp) throws SyntaxError {
     TInfo tinfo = new TInfo();
 

Modified: lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java Mon Mar 16 05:48:14 2015
@@ -59,6 +59,8 @@ import org.apache.solr.handler.component
 import org.apache.solr.highlight.SolrHighlighter;
 import org.apache.solr.parser.QueryParser;
 import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.request.json.RequestUtil;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
@@ -89,7 +91,7 @@ import org.apache.solr.search.SyntaxErro
  * default parameter settings.
  */
 public class SolrPluginUtils {
-  
+
 
   /**
    * Map containing all the possible purposes codes of a request as key and
@@ -131,7 +133,11 @@ public class SolrPluginUtils {
    * @param appends values to be appended to those from the request (or defaults) when dealing with multi-val params, or treated as another layer of defaults for singl-val params.
    * @param invariants values which will be used instead of any request, or default values, regardless of context.
    */
-  public static void setDefaults(SolrQueryRequest req, SolrParams defaults,
+  public static void setDefaults(SolrQueryRequest req, SolrParams defaults, SolrParams appends, SolrParams invariants) {
+    setDefaults(null, req, defaults, appends, invariants);
+  }
+
+  public static void setDefaults(SolrRequestHandler handler, SolrQueryRequest req, SolrParams defaults,
                                  SolrParams appends, SolrParams invariants) {
 
     List<String> paramNames = null;
@@ -157,12 +163,7 @@ public class SolrPluginUtils {
       }
     }
 
-    SolrParams p = req.getParams();
-    p = SolrParams.wrapDefaults(p, defaults);
-    p = SolrParams.wrapAppended(p, appends);
-    p = SolrParams.wrapDefaults(invariants, p);
-
-    req.setParams(p);
+    RequestUtil.processParams(handler, req, defaults, appends, invariants);
   }
 
 

Modified: lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java (original)
+++ lucene/dev/branches/branch_5x/solr/core/src/test/org/apache/solr/search/QueryEqualityTest.java Mon Mar 16 05:48:14 2015
@@ -932,5 +932,19 @@ public class QueryEqualityTest extends S
   }
 
 
+  public void testAggs() throws Exception {
+    assertFuncEquals("agg(avg(foo_i))", "agg(avg(foo_i))");
+    assertFuncEquals("agg(avg(foo_i))", "agg_avg(foo_i)");
+    assertFuncEquals("agg_min(foo_i)", "agg(min(foo_i))");
+    assertFuncEquals("agg_max(foo_i)", "agg(max(foo_i))");
+
+    assertFuncEquals("agg_avg(foo_i)", "agg_avg(foo_i)");
+    assertFuncEquals("agg_sum(foo_i)", "agg_sum(foo_i)");
+    assertFuncEquals("agg_count()", "agg_count()");
+    assertFuncEquals("agg_unique(foo_i)", "agg_unique(foo_i)");
+    assertFuncEquals("agg_sumsq(foo_i)", "agg_sumsq(foo_i)");
+    // assertFuncEquals("agg_stdev(foo_i)", "agg_stdev(foo_i)");
+    // assertFuncEquals("agg_multistat(foo_i)", "agg_multistat(foo_i)");
+  }
 
 }

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/ModifiableSolrParams.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/ModifiableSolrParams.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/ModifiableSolrParams.java (original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/ModifiableSolrParams.java Mon Mar 16 05:48:14 2015
@@ -57,6 +57,11 @@ public class ModifiableSolrParams extend
     }
   }
 
+  public Map<String,String[]> getMap() {
+    return vals;
+  }
+
+
   //----------------------------------------------------------------
   //----------------------------------------------------------------
 

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/MultiMapSolrParams.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/MultiMapSolrParams.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/MultiMapSolrParams.java (original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/MultiMapSolrParams.java Mon Mar 16 05:48:14 2015
@@ -19,6 +19,7 @@ package org.apache.solr.common.params;
 
 import org.apache.solr.common.util.StrUtils;
 
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.io.IOException;
@@ -30,18 +31,33 @@ public class MultiMapSolrParams extends
   protected final Map<String,String[]> map;
 
   public static void addParam(String name, String val, Map<String,String[]> map) {
-      String[] arr = map.get(name);
-      if (arr ==null) {
-        arr =new String[]{val};
-      } else {
-        String[] newarr = new String[arr.length+1];
-        System.arraycopy(arr,0,newarr,0,arr.length);
-        newarr[arr.length]=val;
-        arr =newarr;
-      }
-      map.put(name, arr);
+    String[] arr = map.get(name);
+    if (arr == null) {
+      arr = new String[]{val};
+    } else {
+      String[] newarr = new String[arr.length+1];
+      System.arraycopy(arr, 0, newarr, 0, arr.length);
+      newarr[arr.length] = val;
+      arr = newarr;
+    }
+    map.put(name, arr);
   }
 
+  public static void addParam(String name, String[] vals, Map<String,String[]> map) {
+    String[] arr = map.put(name, vals);
+    if (arr == null) {
+      return;
+    }
+
+    String[] newarr = new String[arr.length+vals.length];
+    System.arraycopy(arr, 0, newarr, 0, arr.length);
+    System.arraycopy(vals, 0, newarr, arr.length, vals.length);
+    arr = newarr;
+
+    map.put(name, arr);
+  }
+
+
   public MultiMapSolrParams(Map<String,String[]> map) {
     this.map = map;
   }
@@ -88,5 +104,35 @@ public class MultiMapSolrParams extends
     return sb.toString();
   }
 
+  /** Returns a MultiMap view of the SolrParams as efficiently as possible.  The returned map may or may not be a backing implementation. */
+  public static Map<String,String[]> asMultiMap(SolrParams params) {
+    return asMultiMap(params, false);
+  }
+
+  /** Returns a MultiMap view of the SolrParams.  A new map will be created if newCopy==true */
+  public static Map<String,String[]> asMultiMap(SolrParams params, boolean newCopy) {
+    if (params instanceof MultiMapSolrParams) {
+      Map<String,String[]> map = ((MultiMapSolrParams)params).getMap();
+      if (newCopy) {
+        return new HashMap<>(map);
+      }
+      return map;
+    } else if (params instanceof ModifiableSolrParams) {
+      Map<String,String[]> map = ((ModifiableSolrParams)params).getMap();
+      if (newCopy) {
+        return new HashMap<>(map);
+      }
+      return map;
+    } else {
+      Map<String,String[]> map = new HashMap<>();
+      Iterator<String> iterator = params.getParameterNamesIterator();
+      while (iterator.hasNext()) {
+        String name = iterator.next();
+        map.put(name, params.getParams(name));
+      }
+      return map;
+    }
+  }
+
 
 }

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java (original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java Mon Mar 16 05:48:14 2015
@@ -320,13 +320,8 @@ public abstract class SolrParams impleme
 
   /** Create SolrParams from NamedList. */
   public static SolrParams toSolrParams(NamedList params) {
-    // if no keys are repeated use the faster MapSolrParams
-    HashMap<String,String> map = new HashMap<>();
-    for (int i=0; i<params.size(); i++) {
-      String prev = map.put(params.getName(i), params.getVal(i).toString());
-      if (prev!=null) return new MultiMapSolrParams(toMultiMap(params));
-    }
-    return new MapSolrParams(map);
+    // always use MultiMap for easier processing further down the chain
+    return new MultiMapSolrParams(toMultiMap(params));
   }
   
   /** Create filtered SolrParams. */

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java (original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java Mon Mar 16 05:48:14 2015
@@ -65,6 +65,12 @@ public class NamedList<T> implements Clo
     nvPairs = new ArrayList<>();
   }
 
+
+  public NamedList(int sz) {
+    nvPairs = new ArrayList<>(sz<<1);
+  }
+
+
   /**
    * Creates a NamedList instance containing the "name,value" pairs contained in the
    * Entry[].

Modified: lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/SimpleOrderedMap.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/SimpleOrderedMap.java?rev=1666876&r1=1666875&r2=1666876&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/SimpleOrderedMap.java (original)
+++ lucene/dev/branches/branch_5x/solr/solrj/src/java/org/apache/solr/common/util/SimpleOrderedMap.java Mon Mar 16 05:48:14 2015
@@ -43,6 +43,10 @@ public class SimpleOrderedMap<T> extends
     super();
   }
 
+  public SimpleOrderedMap(int sz) {
+    super(sz);
+  }
+
   /**
    * Creates an instance backed by an explicitly specified list of
    * pairwise names/values.