You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by is...@apache.org on 2017/07/29 22:00:03 UTC

[26/28] lucene-solr:jira/solr-6630: Merging master

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/NodeConfig.java b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
index 2b70130..5b4debe 100644
--- a/solr/core/src/java/org/apache/solr/core/NodeConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
@@ -33,6 +33,8 @@ public class NodeConfig {
 
   private final Path coreRootDirectory;
 
+  private final Path solrDataHome;
+
   private final Path configSetBaseDirectory;
 
   private final String sharedLibDirectory;
@@ -69,7 +71,7 @@ public class NodeConfig {
 
   private final PluginInfo transientCacheConfig;
 
-  private NodeConfig(String nodeName, Path coreRootDirectory, Path configSetBaseDirectory, String sharedLibDirectory,
+  private NodeConfig(String nodeName, Path coreRootDirectory, Path solrDataHome, Path configSetBaseDirectory, String sharedLibDirectory,
                      PluginInfo shardHandlerFactoryConfig, UpdateShardHandlerConfig updateShardHandlerConfig,
                      String coreAdminHandlerClass, String collectionsAdminHandlerClass,
                      String infoHandlerClass, String configSetsHandlerClass,
@@ -79,6 +81,7 @@ public class NodeConfig {
                      MetricsConfig metricsConfig, PluginInfo transientCacheConfig) {
     this.nodeName = nodeName;
     this.coreRootDirectory = coreRootDirectory;
+    this.solrDataHome = solrDataHome;
     this.configSetBaseDirectory = configSetBaseDirectory;
     this.sharedLibDirectory = sharedLibDirectory;
     this.shardHandlerFactoryConfig = shardHandlerFactoryConfig;
@@ -113,6 +116,10 @@ public class NodeConfig {
     return coreRootDirectory;
   }
 
+  public Path getSolrDataHome() {
+    return solrDataHome;
+  }
+
   public PluginInfo getShardHandlerFactoryPluginInfo() {
     return shardHandlerFactoryConfig;
   }
@@ -195,6 +202,7 @@ public class NodeConfig {
   public static class NodeConfigBuilder {
 
     private Path coreRootDirectory;
+    private Path solrDataHome;
     private Path configSetBaseDirectory;
     private String sharedLibDirectory = "lib";
     private PluginInfo shardHandlerFactoryConfig;
@@ -242,6 +250,11 @@ public class NodeConfig {
       this.nodeName = nodeName;
       this.loader = loader;
       this.coreRootDirectory = loader.getInstancePath();
+      // always init from sysprop because <solrDataHome> config element may be missing
+      String dataHomeProperty = System.getProperty(SolrXmlConfig.SOLR_DATA_HOME);
+      if (dataHomeProperty != null && !dataHomeProperty.isEmpty()) {
+        solrDataHome = loader.getInstancePath().resolve(dataHomeProperty);
+      }
       this.configSetBaseDirectory = loader.getInstancePath().resolve("configsets");
       this.metricsConfig = new MetricsConfig.MetricsConfigBuilder().build();
     }
@@ -251,6 +264,14 @@ public class NodeConfig {
       return this;
     }
 
+    public NodeConfigBuilder setSolrDataHome(String solrDataHomeString) {
+      // keep it null unless explicitly set to non-empty value
+      if (solrDataHomeString != null && !solrDataHomeString.isEmpty()) {
+        this.solrDataHome = loader.getInstancePath().resolve(solrDataHomeString);
+      }
+      return this;
+    }
+
     public NodeConfigBuilder setConfigSetBaseDirectory(String configSetBaseDirectory) {
       this.configSetBaseDirectory = loader.getInstancePath().resolve(configSetBaseDirectory);
       return this;
@@ -344,7 +365,7 @@ public class NodeConfig {
     }
 
     public NodeConfig build() {
-      return new NodeConfig(nodeName, coreRootDirectory, configSetBaseDirectory, sharedLibDirectory, shardHandlerFactoryConfig,
+      return new NodeConfig(nodeName, coreRootDirectory, solrDataHome, configSetBaseDirectory, sharedLibDirectory, shardHandlerFactoryConfig,
                             updateShardHandlerConfig, coreAdminHandlerClass, collectionsAdminHandlerClass, infoHandlerClass, configSetsHandlerClass,
                             logWatcherConfig, cloudConfig, coreLoadThreads, transientCacheSize, useSchemaCache, managementPath, loader, solrProperties,
                             backupRepositoryPlugins, metricsConfig, transientCacheConfig);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/core/SolrCore.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index 5319881..cc6a9c2 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -2565,8 +2565,8 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
   static{
     HashMap<String, QueryResponseWriter> m= new HashMap<>(15, 1);
     m.put("xml", new XMLResponseWriter());
-    m.put("standard", m.get("xml"));
     m.put(CommonParams.JSON, new JSONResponseWriter());
+    m.put("standard", m.get(CommonParams.JSON));
     m.put("geojson", new GeoJSONResponseWriter());
     m.put("graphml", new GraphMLResponseWriter());
     m.put("python", new PythonResponseWriter());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
index e783a89..8cdf947 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
@@ -59,6 +59,7 @@ import static org.apache.solr.common.params.CommonParams.NAME;
 public class SolrXmlConfig {
 
   public final static String SOLR_XML_FILE = "solr.xml";
+  public final static String SOLR_DATA_HOME = "solr.data.home";
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
@@ -249,6 +250,9 @@ public class SolrXmlConfig {
         case "coreRootDirectory":
           builder.setCoreRootDirectory(value);
           break;
+        case "solrDataHome":
+          builder.setSolrDataHome(value);
+          break;
         case "managementPath":
           builder.setManagementPath(value);
           break;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java
index 0770bd4..579e5ef 100644
--- a/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java
@@ -33,6 +33,7 @@ import org.apache.commons.lang.ArrayUtils;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.tokenattributes.BytesTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
@@ -248,8 +249,14 @@ public abstract class AnalysisRequestHandlerBase extends RequestHandlerBase {
     for (int i = 0; i < tokens.length; i++) {
       AttributeSource token = tokens[i];
       final NamedList<Object> tokenNamedList = new SimpleOrderedMap<>();
-      final TermToBytesRefAttribute termAtt = token.getAttribute(TermToBytesRefAttribute.class);
-      BytesRef rawBytes = termAtt.getBytesRef();
+      final BytesRef rawBytes;
+      if (token.hasAttribute(BytesTermAttribute.class)) {
+        final BytesTermAttribute bytesAtt = token.getAttribute(BytesTermAttribute.class);
+        rawBytes = bytesAtt.getBytesRef(); 
+      } else {
+        final TermToBytesRefAttribute termAtt = token.getAttribute(TermToBytesRefAttribute.class);
+        rawBytes = termAtt.getBytesRef();
+      }
       final String text = fieldType.indexedToReadable(rawBytes, new CharsRefBuilder()).toString();
       tokenNamedList.add("text", text);
       

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/handler/ExportWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/ExportWriter.java b/solr/core/src/java/org/apache/solr/handler/ExportWriter.java
index 61f937c..f618eef 100644
--- a/solr/core/src/java/org/apache/solr/handler/ExportWriter.java
+++ b/solr/core/src/java/org/apache/solr/handler/ExportWriter.java
@@ -17,10 +17,6 @@
 
 package org.apache.solr.handler;
 
-import static java.util.Collections.singletonList;
-import static java.util.Collections.singletonMap;
-import static org.apache.solr.common.util.Utils.makeMap;
-
 import java.io.Closeable;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -38,6 +34,7 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.index.SortedNumericDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
@@ -53,8 +50,8 @@ import org.apache.lucene.util.LongValues;
 import org.apache.lucene.util.NumericUtils;
 import org.apache.solr.client.solrj.impl.BinaryResponseParser;
 import org.apache.solr.common.IteratorWriter;
-import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.MapWriter.EntryWriter;
+import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.PushWriter;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.SolrParams;
@@ -82,6 +79,10 @@ import org.apache.solr.search.SyntaxError;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+import static org.apache.solr.common.util.Utils.makeMap;
+
 public class ExportWriter implements SolrCore.RawWriter, Closeable {
   private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private OutputStreamWriter respWriter;
@@ -1257,7 +1258,7 @@ public class ExportWriter implements SolrCore.RawWriter, Closeable {
 
     protected SortedDocValues vals;
 
-    protected MultiDocValues.OrdinalMap ordinalMap;
+    protected OrdinalMap ordinalMap;
     protected LongValues globalOrds;
     protected SortedDocValues currentVals;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
index 2d545ba..1da8f85 100644
--- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
@@ -205,7 +205,7 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw
 
   private final Map<String, FileInfo> confFileInfoCache = new HashMap<>();
 
-  private Integer reserveCommitDuration = readIntervalMs("00:00:10");
+  private Long reserveCommitDuration = readIntervalMs("00:00:10");
 
   volatile IndexCommit indexCommitPoint;
 
@@ -1695,8 +1695,8 @@ public class ReplicationHandler extends RequestHandlerBase implements SolrCoreAw
 
   }
 
-  private static Integer readIntervalMs(String interval) {
-    return (int) TimeUnit.MILLISECONDS.convert(readIntervalNs(interval), TimeUnit.NANOSECONDS);
+  private static Long readIntervalMs(String interval) {
+    return TimeUnit.MILLISECONDS.convert(readIntervalNs(interval), TimeUnit.NANOSECONDS);
   }
 
   private static Long readIntervalNs(String interval) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
index 3901c61..d52972d 100644
--- a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
@@ -217,8 +217,9 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
         .withFunctionName("scale", ScaleEvaluator.class)
         .withFunctionName("sequence", SequenceEvaluator.class)
         .withFunctionName("addAll", AddAllEvaluator.class)
+        .withFunctionName("residuals", ResidualsEvaluator.class)
+        .withFunctionName("plot", PlotStream.class)
 
-        
         // Boolean Stream Evaluators
         .withFunctionName("and", AndEvaluator.class)
         .withFunctionName("eor", ExclusiveOrEvaluator.class)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
index 1b72c92..cbaa4ef 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
@@ -126,6 +126,7 @@ import static org.apache.solr.common.params.CoreAdminParams.DELETE_DATA_DIR;
 import static org.apache.solr.common.params.CoreAdminParams.DELETE_INDEX;
 import static org.apache.solr.common.params.CoreAdminParams.DELETE_INSTANCE_DIR;
 import static org.apache.solr.common.params.CoreAdminParams.INSTANCE_DIR;
+import static org.apache.solr.common.params.CoreAdminParams.ULOG_DIR;
 import static org.apache.solr.common.params.ShardParams._ROUTE_;
 import static org.apache.solr.common.util.StrUtils.formatString;
 
@@ -633,6 +634,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
           CoreAdminParams.NAME,
           INSTANCE_DIR,
           DATA_DIR,
+          ULOG_DIR,
           REPLICA_TYPE);
       return copyPropertiesWithPrefix(req.getParams(), props, COLL_PROP_PREFIX);
     }),
@@ -880,14 +882,26 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
       rsp.add(SolrSnapshotManager.SNAPSHOTS_INFO, snapshots);
       return null;
     }),
-    REPLACENODE_OP(REPLACENODE, (req, rsp, h) -> req.getParams().required().getAll(req.getParams().getAll(null, "parallel"), "source", "target")),
+    REPLACENODE_OP(REPLACENODE, (req, rsp, h) -> {
+      SolrParams params = req.getParams();
+      String sourceNode = params.get(CollectionParams.SOURCE_NODE, params.get("source"));
+      if (sourceNode == null) {
+        throw new SolrException(ErrorCode.BAD_REQUEST, CollectionParams.SOURCE_NODE + " is a require parameter");
+      }
+      String targetNode = params.get(CollectionParams.TARGET_NODE, params.get("target"));
+      if (targetNode == null) {
+        throw new SolrException(ErrorCode.BAD_REQUEST, CollectionParams.TARGET_NODE + " is a require parameter");
+      }
+      return params.getAll(null, "source", "target", CollectionParams.SOURCE_NODE, CollectionParams.TARGET_NODE);
+    }),
     MOVEREPLICA_OP(MOVEREPLICA, (req, rsp, h) -> {
       Map<String, Object> map = req.getParams().required().getAll(null,
           COLLECTION_PROP);
 
       return req.getParams().getAll(map,
-          "fromNode",
-          "targetNode",
+          CollectionParams.FROM_NODE,
+          CollectionParams.SOURCE_NODE,
+          CollectionParams.TARGET_NODE,
           "replica",
           "shard");
     }),

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java
index 4faa466..f9a3c05 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/SolrInfoMBeanHandler.java
@@ -209,14 +209,16 @@ public class SolrInfoMBeanHandler extends RequestHandlerBase {
     for(int i=0; i<ref.size(); i++) {
       String name = ref.getName(i);
       Object r = ref.getVal(i);
-      Object n = now.remove(name);
-      if(n == null) {
-        if(r!=null) {
-          out.add("REMOVE "+name, r);
+      Object n = now.get(name);
+      if (n == null) {
+        if (r != null) {
+          out.add("REMOVE " + name, r);
+          now.remove(name);
         }
       }
-      else {
-        out.add(name, diffObject(r,n));
+      else if (r != null) {
+        out.add(name, diffObject(r, n));
+        now.remove(name);
       }
     }
     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java b/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java
index 10c5b13..e2bcef8 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ExpandComponent.java
@@ -24,15 +24,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import com.carrotsearch.hppc.IntHashSet;
-import com.carrotsearch.hppc.IntObjectHashMap;
-import com.carrotsearch.hppc.LongHashSet;
-import com.carrotsearch.hppc.LongObjectHashMap;
-import com.carrotsearch.hppc.LongObjectMap;
-import com.carrotsearch.hppc.cursors.IntObjectCursor;
-import com.carrotsearch.hppc.cursors.LongCursor;
-import com.carrotsearch.hppc.cursors.LongObjectCursor;
-import com.carrotsearch.hppc.cursors.ObjectCursor;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.DocValuesType;
 import org.apache.lucene.index.FieldInfo;
@@ -42,6 +33,7 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery;
@@ -88,6 +80,16 @@ import org.apache.solr.uninverting.UninvertingReader;
 import org.apache.solr.util.plugin.PluginInfoInitialized;
 import org.apache.solr.util.plugin.SolrCoreAware;
 
+import com.carrotsearch.hppc.IntHashSet;
+import com.carrotsearch.hppc.IntObjectHashMap;
+import com.carrotsearch.hppc.LongHashSet;
+import com.carrotsearch.hppc.LongObjectHashMap;
+import com.carrotsearch.hppc.LongObjectMap;
+import com.carrotsearch.hppc.cursors.IntObjectCursor;
+import com.carrotsearch.hppc.cursors.LongCursor;
+import com.carrotsearch.hppc.cursors.LongObjectCursor;
+import com.carrotsearch.hppc.cursors.ObjectCursor;
+
 /**
  * The ExpandComponent is designed to work with the CollapsingPostFilter.
  * The CollapsingPostFilter collapses a result set on a field.
@@ -274,7 +276,7 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
     IntObjectHashMap<BytesRef> ordBytes = null;
     if(values != null) {
       groupBits = new FixedBitSet(values.getValueCount());
-      MultiDocValues.OrdinalMap ordinalMap = null;
+      OrdinalMap ordinalMap = null;
       SortedDocValues[] sortedDocValues = null;
       LongValues segmentOrdinalMap = null;
       SortedDocValues currentValues = null;
@@ -520,7 +522,7 @@ public class ExpandComponent extends SearchComponent implements PluginInfoInitia
 
   private static class GroupExpandCollector implements Collector, GroupCollector {
     private SortedDocValues docValues;
-    private MultiDocValues.OrdinalMap ordinalMap;
+    private OrdinalMap ordinalMap;
     private SortedDocValues segmentValues;
     private LongValues segmentOrdinalMap;
     private MultiDocValues.MultiSortedDocValues multiSortedDocValues;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
index ad1e81f..2d612e9 100644
--- a/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
+++ b/solr/core/src/java/org/apache/solr/index/SlowCompositeReaderWrapper.java
@@ -22,7 +22,7 @@ import java.util.Map;
 
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.MultiDocValues.MultiSortedDocValues;
-import org.apache.lucene.index.MultiDocValues.OrdinalMap;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.Version;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java b/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java
index e9498f8..d77c73d 100644
--- a/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/DocValuesFacets.java
@@ -22,9 +22,9 @@ import java.util.function.Predicate;
 
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.MultiDocValues.MultiSortedSetDocValues;
-import org.apache.lucene.index.MultiDocValues.OrdinalMap;
+import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.search.DocIdSet;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/request/DocValuesStats.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/request/DocValuesStats.java b/solr/core/src/java/org/apache/solr/request/DocValuesStats.java
index 4b1fe84..dae9943 100644
--- a/solr/core/src/java/org/apache/solr/request/DocValuesStats.java
+++ b/solr/core/src/java/org/apache/solr/request/DocValuesStats.java
@@ -22,9 +22,9 @@ import java.util.Map;
 
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.MultiDocValues.MultiSortedSetDocValues;
-import org.apache.lucene.index.MultiDocValues.OrdinalMap;
+import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.search.DocIdSet;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/request/IntervalFacets.java b/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
index 9a23a83..c2d6ab0 100644
--- a/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/IntervalFacets.java
@@ -216,9 +216,7 @@ public class IntervalFacets implements Iterable<FacetInterval> {
             longs = new FilterNumericDocValues(DocValues.getNumeric(ctx.reader(), fieldName)) {
               @Override
               public long longValue() throws IOException {
-                long bits = super.longValue();
-                if (bits < 0) bits ^= 0x7fffffffffffffffL;
-                return bits;
+                return NumericUtils.sortableFloatBits((int)super.longValue());
               }
             };
             break;
@@ -227,9 +225,7 @@ public class IntervalFacets implements Iterable<FacetInterval> {
             longs = new FilterNumericDocValues(DocValues.getNumeric(ctx.reader(), fieldName)) {
               @Override
               public long longValue() throws IOException {
-                long bits = super.longValue();
-                if (bits < 0) bits ^= 0x7fffffffffffffffL;
-                return bits;
+               return NumericUtils.sortableDoubleBits(super.longValue());
               }
             };
             break;
@@ -443,12 +439,12 @@ public class IntervalFacets implements Iterable<FacetInterval> {
     INCLUDED,
     GREATER_THAN_END,
   }
-
+  
   /**
    * Helper class to match and count of documents in specified intervals
    */
   public static class FacetInterval {
-
+    
     /**
      * Key to represent this interval
      */
@@ -508,6 +504,11 @@ public class IntervalFacets implements Iterable<FacetInterval> {
      * The current count of documents in that match this interval
      */
     private int count;
+    
+    /**
+     * If this field is set to true, this interval {@code #getCount()} will always return 0.
+     */
+    private boolean includeNoDocs = false;
 
     /**
      * 
@@ -650,7 +651,14 @@ public class IntervalFacets implements Iterable<FacetInterval> {
             throw new AssertionError();
         }
         if (startOpen) {
-          startLimit++;
+          if (startLimit == Long.MAX_VALUE) {
+            /*
+             * This interval can match no docs
+             */
+            includeNoDocs = true;
+          } else {
+            startLimit++;
+          }
         }
       }
 
@@ -678,7 +686,14 @@ public class IntervalFacets implements Iterable<FacetInterval> {
             throw new AssertionError();
         }
         if (endOpen) {
-          endLimit--;
+          if (endLimit == Long.MIN_VALUE) {
+            /*
+             * This interval can match no docs
+             */
+            includeNoDocs = true;
+          } else {
+            endLimit--;
+          }
         }
       }
     }
@@ -886,6 +901,9 @@ public class IntervalFacets implements Iterable<FacetInterval> {
      * @return The count of document that matched this interval
      */
     public int getCount() {
+      if (includeNoDocs) {
+        return 0;
+      }
       return this.count;
     }
 
@@ -910,7 +928,6 @@ public class IntervalFacets implements Iterable<FacetInterval> {
    */
   @Override
   public Iterator<FacetInterval> iterator() {
-
     return new ArrayList<FacetInterval>(Arrays.asList(intervals)).iterator();
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
index 261daee..4d052ae 100644
--- a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
@@ -84,7 +84,7 @@ public abstract class TextResponseWriter implements PushWriter {
     this.req = req;
     this.rsp = rsp;
     String indent = req.getParams().get("indent");
-    if (indent != null && !"".equals(indent) && !"off".equals(indent)) {
+    if (null == indent || !("off".equals(indent) || "false".equals(indent))){
       doIndent=true;
     }
     returnFields = rsp.getReturnFields();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java b/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java
index 45b0efc..ff7c061 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java
@@ -17,6 +17,7 @@
 package org.apache.solr.response.transform;
 
 import java.io.IOException;
+import java.util.Set;
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
@@ -39,6 +40,7 @@ import org.apache.solr.search.DocList;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.QueryWrapperFilter;
 import org.apache.solr.search.SyntaxError;
+import org.apache.solr.search.SolrDocumentFetcher;
 
 /**
  *
@@ -135,12 +137,21 @@ class ChildDocTransformer extends DocTransformer {
       Query query = new ToChildBlockJoinQuery(parentQuery, parentsFilter);
       DocList children = context.getSearcher().getDocList(query, childFilterQuery, new Sort(), 0, limit);
       if(children.matches() > 0) {
+        SolrDocumentFetcher docFetcher = context.getSearcher().getDocFetcher();
+
+        Set<String> dvFieldsToReturn = docFetcher.getNonStoredDVs(true);
+        boolean shouldDecorateWithDVs = dvFieldsToReturn.size() > 0;
         DocIterator i = children.iterator();
+
         while(i.hasNext()) {
           Integer childDocNum = i.next();
           Document childDoc = context.getSearcher().doc(childDocNum);
           SolrDocument solrChildDoc = DocsStreamer.convertLuceneDocToSolrDoc(childDoc, schema);
 
+          if (shouldDecorateWithDVs) {
+            docFetcher.decorateDocValueFields(solrChildDoc, childDocNum, dvFieldsToReturn);
+          }
+
           // TODO: future enhancement...
           // support an fl local param in the transformer, which is used to build
           // a private ReturnFields instance that we use to prune unwanted field 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/CollationField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/CollationField.java b/solr/core/src/java/org/apache/solr/schema/CollationField.java
index c6a4f81..b8285aa 100644
--- a/solr/core/src/java/org/apache/solr/schema/CollationField.java
+++ b/solr/core/src/java/org/apache/solr/schema/CollationField.java
@@ -241,7 +241,7 @@ public class CollationField extends FieldType {
     BytesRef low = part1 == null ? null : getCollationKey(f, part1);
     BytesRef high = part2 == null ? null : getCollationKey(f, part2);
     if (!field.indexed() && field.hasDocValues()) {
-      return SortedSetDocValuesField.newRangeQuery(
+      return SortedSetDocValuesField.newSlowRangeQuery(
           field.getName(), low, high, minInclusive, maxInclusive);
     } else {
       return new TermRangeQuery(field.getName(), low, high, minInclusive, maxInclusive);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/DatePointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/DatePointField.java b/solr/core/src/java/org/apache/solr/schema/DatePointField.java
index ea81ea3..e43f706 100644
--- a/solr/core/src/java/org/apache/solr/schema/DatePointField.java
+++ b/solr/core/src/java/org/apache/solr/schema/DatePointField.java
@@ -27,6 +27,7 @@ import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
 import org.apache.lucene.queries.function.valuesource.MultiValuedLongFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.SortedNumericSelector;
@@ -123,6 +124,7 @@ public class DatePointField extends PointField implements DateValueFieldType {
     } else {
       actualMin = DateMathParser.parseMath(null, min).getTime();
       if (!minInclusive) {
+        if (actualMin == Long.MAX_VALUE) return new MatchNoDocsQuery();
         actualMin++;
       }
     }
@@ -131,6 +133,7 @@ public class DatePointField extends PointField implements DateValueFieldType {
     } else {
       actualMax = DateMathParser.parseMath(null, max).getTime();
       if (!maxInclusive) {
+        if (actualMax == Long.MIN_VALUE) return new MatchNoDocsQuery();
         actualMax--;
       }
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/DoublePointField.java b/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
index d2cf6ed..edc7c38 100644
--- a/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
+++ b/solr/core/src/java/org/apache/solr/schema/DoublePointField.java
@@ -18,7 +18,6 @@
 package org.apache.solr.schema;
 
 import java.util.Collection;
-
 import org.apache.lucene.document.DoublePoint;
 import org.apache.lucene.document.StoredField;
 import org.apache.lucene.index.DocValuesType;
@@ -26,6 +25,7 @@ import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
 import org.apache.lucene.queries.function.valuesource.MultiValuedDoubleFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.SortedNumericSelector;
@@ -63,6 +63,7 @@ public class DoublePointField extends PointField implements DoubleValueFieldType
     } else {
       actualMin = parseDoubleFromUser(field.getName(), min);
       if (!minInclusive) {
+        if (actualMin == Double.POSITIVE_INFINITY) return new MatchNoDocsQuery();
         actualMin = DoublePoint.nextUp(actualMin);
       }
     }
@@ -71,6 +72,7 @@ public class DoublePointField extends PointField implements DoubleValueFieldType
     } else {
       actualMax = parseDoubleFromUser(field.getName(), max);
       if (!maxInclusive) {
+        if (actualMax == Double.NEGATIVE_INFINITY) return new MatchNoDocsQuery();
         actualMax = DoublePoint.nextDown(actualMax);
       }
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/EnumField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/EnumField.java b/solr/core/src/java/org/apache/solr/schema/EnumField.java
index 60e65d5..a60cd80 100644
--- a/solr/core/src/java/org/apache/solr/schema/EnumField.java
+++ b/solr/core/src/java/org/apache/solr/schema/EnumField.java
@@ -386,8 +386,11 @@ public class EnumField extends PrimitiveFieldType {
       return null;
     }
     final Integer intValue = stringValueToIntValue(value.toString());
-    if (intValue == null || intValue.equals(DEFAULT_VALUE))
-      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown value for enum field: " + value.toString());
+    if (intValue == null || intValue.equals(DEFAULT_VALUE)) {
+      String exceptionMessage = String.format(Locale.ENGLISH, "Unknown value for enum field: %s, value: %s",
+          field.getName(), value.toString());
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,  exceptionMessage);
+    }
 
     final LegacyFieldType newType = new LegacyFieldType();
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java b/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
index da4b4db..db2d11b 100644
--- a/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
+++ b/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.SortField;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.response.TextResponseWriter;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.function.FileFloatSource;
@@ -122,5 +123,10 @@ public class ExternalFileField extends FieldType implements SchemaAware {
   @Override
   public void inform(IndexSchema schema) {
     this.schema = schema;
+    
+    if (keyFieldName != null && schema.getFieldType(keyFieldName).isPointField()) {
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+          "keyField '" + keyFieldName + "' has a Point field type, which is not supported.");
+    }
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/FieldType.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldType.java b/solr/core/src/java/org/apache/solr/schema/FieldType.java
index 388b659..3d38844 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldType.java
@@ -30,6 +30,7 @@ import java.util.Set;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.tokenattributes.BytesTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.util.CharFilterFactory;
@@ -479,14 +480,20 @@ public abstract class FieldType extends FieldProperties {
       Tokenizer ts = new Tokenizer() {
         final char[] cbuf = new char[maxChars];
         final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
+        final BytesTermAttribute bytesAtt = isPointField() ? addAttribute(BytesTermAttribute.class) : null;
         final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
         @Override
         public boolean incrementToken() throws IOException {
           clearAttributes();
           int n = input.read(cbuf,0,maxChars);
           if (n<=0) return false;
-          String s = toInternal(new String(cbuf,0,n));
-          termAtt.setEmpty().append(s);
+          if (isPointField()) {
+            BytesRef b = ((PointField)FieldType.this).toInternalByteRef(new String(cbuf, 0, n));
+            bytesAtt.setBytesRef(b);
+          } else {
+            String s = toInternal(new String(cbuf, 0, n));
+            termAtt.setEmpty().append(s);
+          }
           offsetAtt.setOffset(correctOffset(0),correctOffset(n));
           return true;
         }
@@ -720,7 +727,7 @@ public abstract class FieldType extends FieldProperties {
     final BytesRef miValue = part1 == null ? null : new BytesRef(toInternal(part1));
     final BytesRef maxValue = part2 == null ? null : new BytesRef(toInternal(part2));
     if (field.hasDocValues() && !field.indexed()) {
-      return SortedSetDocValuesField.newRangeQuery(
+      return SortedSetDocValuesField.newSlowRangeQuery(
             field.getName(),
             miValue, maxValue,
             minInclusive, maxInclusive);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/FloatPointField.java b/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
index e1a9741..c70655a 100644
--- a/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
+++ b/solr/core/src/java/org/apache/solr/schema/FloatPointField.java
@@ -18,7 +18,6 @@
 package org.apache.solr.schema;
 
 import java.util.Collection;
-
 import org.apache.lucene.document.FloatPoint;
 import org.apache.lucene.document.StoredField;
 import org.apache.lucene.index.DocValuesType;
@@ -26,6 +25,7 @@ import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
 import org.apache.lucene.queries.function.valuesource.MultiValuedFloatFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.SortedNumericSelector;
@@ -63,6 +63,7 @@ public class FloatPointField extends PointField implements FloatValueFieldType {
     } else {
       actualMin = parseFloatFromUser(field.getName(), min);
       if (!minInclusive) {
+        if (actualMin == Float.POSITIVE_INFINITY) return new MatchNoDocsQuery();
         actualMin = FloatPoint.nextUp(actualMin);
       }
     }
@@ -71,6 +72,7 @@ public class FloatPointField extends PointField implements FloatValueFieldType {
     } else {
       actualMax = parseFloatFromUser(field.getName(), max);
       if (!maxInclusive) {
+        if (actualMax == Float.NEGATIVE_INFINITY) return new MatchNoDocsQuery();
         actualMax = FloatPoint.nextDown(actualMax);
       }
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/IntPointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/IntPointField.java b/solr/core/src/java/org/apache/solr/schema/IntPointField.java
index 7d36612..d5e4aec 100644
--- a/solr/core/src/java/org/apache/solr/schema/IntPointField.java
+++ b/solr/core/src/java/org/apache/solr/schema/IntPointField.java
@@ -25,6 +25,7 @@ import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.IntFieldSource;
 import org.apache.lucene.queries.function.valuesource.MultiValuedIntFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.SortedNumericSelector;
@@ -66,6 +67,7 @@ public class IntPointField extends PointField implements IntValueFieldType {
     } else {
       actualMin = parseIntFromUser(field.getName(), min);
       if (!minInclusive) {
+        if (actualMin == Integer.MAX_VALUE) return new MatchNoDocsQuery();
         actualMin++;
       }
     }
@@ -74,6 +76,7 @@ public class IntPointField extends PointField implements IntValueFieldType {
     } else {
       actualMax = parseIntFromUser(field.getName(), max);
       if (!maxInclusive) {
+        if (actualMax == Integer.MIN_VALUE) return new MatchNoDocsQuery();
         actualMax--;
       }
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/LongPointField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/LongPointField.java b/solr/core/src/java/org/apache/solr/schema/LongPointField.java
index b2d8a3a..7e3f5e1 100644
--- a/solr/core/src/java/org/apache/solr/schema/LongPointField.java
+++ b/solr/core/src/java/org/apache/solr/schema/LongPointField.java
@@ -25,6 +25,7 @@ import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
 import org.apache.lucene.queries.function.valuesource.MultiValuedLongFieldSource;
+import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.util.BytesRef;
@@ -65,6 +66,7 @@ public class LongPointField extends PointField implements LongValueFieldType {
     } else {
       actualMin = parseLongFromUser(field.getName(), min);
       if (!minInclusive) {
+        if (actualMin == Long.MAX_VALUE) return new MatchNoDocsQuery();
         actualMin++;
       }
     }
@@ -73,6 +75,7 @@ public class LongPointField extends PointField implements LongValueFieldType {
     } else {
       actualMax = parseLongFromUser(field.getName(), max);
       if (!maxInclusive) {
+        if (actualMax == Long.MIN_VALUE) return new MatchNoDocsQuery();
         actualMax--;
       }
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/schema/NumericFieldType.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/NumericFieldType.java b/solr/core/src/java/org/apache/solr/schema/NumericFieldType.java
index c79f465..86697e5 100644
--- a/solr/core/src/java/org/apache/solr/schema/NumericFieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/NumericFieldType.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr.schema;
 
+import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.document.FloatPoint;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedNumericDocValuesField;
 import org.apache.lucene.queries.function.ValueSource;
@@ -40,14 +42,8 @@ public abstract class NumericFieldType extends PrimitiveFieldType {
     return type;
   }
 
-  private static long FLOAT_NEGATIVE_INFINITY_BITS = (long)Float.floatToIntBits(Float.NEGATIVE_INFINITY);
-  private static long DOUBLE_NEGATIVE_INFINITY_BITS = Double.doubleToLongBits(Double.NEGATIVE_INFINITY);
-  private static long FLOAT_POSITIVE_INFINITY_BITS = (long)Float.floatToIntBits(Float.POSITIVE_INFINITY);
-  private static long DOUBLE_POSITIVE_INFINITY_BITS = Double.doubleToLongBits(Double.POSITIVE_INFINITY);
   private static long FLOAT_MINUS_ZERO_BITS = (long)Float.floatToIntBits(-0f);
   private static long DOUBLE_MINUS_ZERO_BITS = Double.doubleToLongBits(-0d);
-  private static long FLOAT_ZERO_BITS = (long)Float.floatToIntBits(0f);
-  private static long DOUBLE_ZERO_BITS = Double.doubleToLongBits(0d);
 
   protected Query getDocValuesRangeQuery(QParser parser, SchemaField field, String min, String max,
       boolean minInclusive, boolean maxInclusive) {
@@ -89,50 +85,119 @@ public abstract class NumericFieldType extends PrimitiveFieldType {
   protected Query getRangeQueryForFloatDoubleDocValues(SchemaField sf, String min, String max, boolean minInclusive, boolean maxInclusive) {
     Query query;
     String fieldName = sf.getName();
-
-    Number minVal = min == null ? null : getNumberType() == NumberType.FLOAT ? parseFloatFromUser(sf.getName(), min): parseDoubleFromUser(sf.getName(), min);
-    Number maxVal = max == null ? null : getNumberType() == NumberType.FLOAT ? parseFloatFromUser(sf.getName(), max): parseDoubleFromUser(sf.getName(), max);
-    
-    Long minBits = 
-        min == null ? null : getNumberType() == NumberType.FLOAT ? (long) Float.floatToIntBits(minVal.floatValue()): Double.doubleToLongBits(minVal.doubleValue());
-    Long maxBits = 
-        max == null ? null : getNumberType() == NumberType.FLOAT ? (long) Float.floatToIntBits(maxVal.floatValue()): Double.doubleToLongBits(maxVal.doubleValue());
-    
-    long negativeInfinityBits = getNumberType() == NumberType.FLOAT ? FLOAT_NEGATIVE_INFINITY_BITS : DOUBLE_NEGATIVE_INFINITY_BITS;
-    long positiveInfinityBits = getNumberType() == NumberType.FLOAT ? FLOAT_POSITIVE_INFINITY_BITS : DOUBLE_POSITIVE_INFINITY_BITS;
-    long minusZeroBits = getNumberType() == NumberType.FLOAT ? FLOAT_MINUS_ZERO_BITS : DOUBLE_MINUS_ZERO_BITS;
-    long zeroBits = getNumberType() == NumberType.FLOAT ? FLOAT_ZERO_BITS : DOUBLE_ZERO_BITS;
-    
+    long minBits, maxBits;
+    boolean minNegative, maxNegative;
+    Number minVal, maxVal;
+    if (getNumberType() == NumberType.FLOAT) {
+      if (min == null) {
+        minVal = Float.NEGATIVE_INFINITY;
+      } else {
+        minVal = parseFloatFromUser(sf.getName(), min);
+        if (!minInclusive) {
+          if (minVal.floatValue() == Float.POSITIVE_INFINITY) return new MatchNoDocsQuery();
+          minVal = FloatPoint.nextUp(minVal.floatValue());
+        }
+      }
+      if (max == null) {
+        maxVal = Float.POSITIVE_INFINITY;
+      } else {
+        maxVal = parseFloatFromUser(sf.getName(), max);
+        if (!maxInclusive) {
+          if (maxVal.floatValue() == Float.NEGATIVE_INFINITY) return new MatchNoDocsQuery();
+          maxVal = FloatPoint.nextDown(maxVal.floatValue());
+        }
+      }
+      minBits = Float.floatToIntBits(minVal.floatValue());
+      maxBits = Float.floatToIntBits(maxVal.floatValue());
+      minNegative = minVal.floatValue() < 0f || minBits == FLOAT_MINUS_ZERO_BITS;
+      maxNegative = maxVal.floatValue() < 0f || maxBits == FLOAT_MINUS_ZERO_BITS;
+    } else {
+      assert getNumberType() == NumberType.DOUBLE;
+      if (min == null) {
+        minVal = Double.NEGATIVE_INFINITY;
+      } else {
+        minVal = parseDoubleFromUser(sf.getName(), min);
+        if (!minInclusive) {
+          if (minVal.doubleValue() == Double.POSITIVE_INFINITY) return new MatchNoDocsQuery();
+          minVal = DoublePoint.nextUp(minVal.doubleValue());
+        }
+      }
+      if (max == null) {
+        maxVal = Double.POSITIVE_INFINITY;
+      } else {
+        maxVal = parseDoubleFromUser(sf.getName(), max);
+        if (!maxInclusive) {
+          if (maxVal.doubleValue() == Double.NEGATIVE_INFINITY) return new MatchNoDocsQuery();
+          maxVal = DoublePoint.nextDown(maxVal.doubleValue());
+        }
+      }
+      minBits = Double.doubleToLongBits(minVal.doubleValue());
+      maxBits = Double.doubleToLongBits(maxVal.doubleValue());
+      minNegative = minVal.doubleValue() < 0d || minBits == DOUBLE_MINUS_ZERO_BITS;
+      maxNegative = maxVal.doubleValue() < 0d || maxBits == DOUBLE_MINUS_ZERO_BITS;
+    }
     // If min is negative (or -0d) and max is positive (or +0d), then issue a FunctionRangeQuery
-    if ((minVal == null || minVal.doubleValue() < 0d || minBits == minusZeroBits) && 
-        (maxVal == null || (maxVal.doubleValue() > 0d || maxBits == zeroBits))) {
-
+    if (minNegative && !maxNegative) {
       ValueSource vs = getValueSource(sf, null);
-      query = new FunctionRangeQuery(new ValueSourceRangeFilter(vs, min, max, minInclusive, maxInclusive));
-
-    } else { // If both max and min are negative (or -0d), then issue range query with max and min reversed
-      if ((minVal == null || minVal.doubleValue() < 0d || minBits == minusZeroBits) &&
-          (maxVal != null && (maxVal.doubleValue() < 0d || maxBits == minusZeroBits))) {
-        query = numericDocValuesRangeQuery
-            (fieldName, maxBits, (min == null ? Long.valueOf(negativeInfinityBits) : minBits), maxInclusive, minInclusive, false);
-      } else { // If both max and min are positive, then issue range query
-        query = numericDocValuesRangeQuery
-            (fieldName, minBits, (max == null ? Long.valueOf(positiveInfinityBits) : maxBits), minInclusive, maxInclusive, false);
-      }
+      query = new FunctionRangeQuery(new ValueSourceRangeFilter(vs, minVal.toString(), maxVal.toString(), true, true));
+    } else if (minNegative && maxNegative) {// If both max and min are negative (or -0d), then issue range query with max and min reversed
+      query = numericDocValuesRangeQuery
+          (fieldName, maxBits, minBits, true, true, false);
+    } else { // If both max and min are positive, then issue range query
+      query = numericDocValuesRangeQuery
+          (fieldName, minBits, maxBits, true, true, false);
     }
     return query;
   }
-  
+
   protected Query getRangeQueryForMultiValuedDoubleDocValues(SchemaField sf, String min, String max, boolean minInclusive, boolean maxInclusive) {
-    Long minBits = min == null ? NumericUtils.doubleToSortableLong(Double.NEGATIVE_INFINITY): NumericUtils.doubleToSortableLong(parseDoubleFromUser(sf.getName(), min));
-    Long maxBits = max == null ? NumericUtils.doubleToSortableLong(Double.POSITIVE_INFINITY): NumericUtils.doubleToSortableLong(parseDoubleFromUser(sf.getName(), max));
-    return numericDocValuesRangeQuery(sf.getName(), minBits, maxBits, minInclusive, maxInclusive, true);
+    double minVal,maxVal;
+    if (min == null) {
+      minVal = Double.NEGATIVE_INFINITY;
+    } else {
+      minVal = parseDoubleFromUser(sf.getName(), min);
+      if (!minInclusive) {
+        if (minVal == Double.POSITIVE_INFINITY) return new MatchNoDocsQuery();
+        minVal = DoublePoint.nextUp(minVal);
+      }
+    }
+    if (max == null) {
+      maxVal = Double.POSITIVE_INFINITY;
+    } else {
+      maxVal = parseDoubleFromUser(sf.getName(), max);
+      if (!maxInclusive) {
+        if (maxVal == Double.NEGATIVE_INFINITY) return new MatchNoDocsQuery();
+        maxVal = DoublePoint.nextDown(maxVal);
+      }
+    }
+    Long minBits = NumericUtils.doubleToSortableLong(minVal);
+    Long maxBits = NumericUtils.doubleToSortableLong(maxVal);
+    return numericDocValuesRangeQuery(sf.getName(), minBits, maxBits, true, true, true);
   }
-  
+
   protected Query getRangeQueryForMultiValuedFloatDocValues(SchemaField sf, String min, String max, boolean minInclusive, boolean maxInclusive) {
-    Long minBits = (long)(min == null ? NumericUtils.floatToSortableInt(Float.NEGATIVE_INFINITY): NumericUtils.floatToSortableInt(parseFloatFromUser(sf.getName(), min)));
-    Long maxBits = (long)(max == null ? NumericUtils.floatToSortableInt(Float.POSITIVE_INFINITY): NumericUtils.floatToSortableInt(parseFloatFromUser(sf.getName(), max)));
-    return numericDocValuesRangeQuery(sf.getName(), minBits, maxBits, minInclusive, maxInclusive, true);
+    float minVal,maxVal;
+    if (min == null) {
+      minVal = Float.NEGATIVE_INFINITY;
+    } else {
+      minVal = parseFloatFromUser(sf.getName(), min);
+      if (!minInclusive) {
+        if (minVal == Float.POSITIVE_INFINITY) return new MatchNoDocsQuery();
+        minVal = FloatPoint.nextUp(minVal);
+      }
+    }
+    if (max == null) {
+      maxVal = Float.POSITIVE_INFINITY;
+    } else {
+      maxVal = parseFloatFromUser(sf.getName(), max);
+      if (!maxInclusive) {
+        if (maxVal == Float.NEGATIVE_INFINITY) return new MatchNoDocsQuery();
+        maxVal = FloatPoint.nextDown(maxVal);
+      }
+    }
+    Long minBits = (long)NumericUtils.floatToSortableInt(minVal);
+    Long maxBits = (long)NumericUtils.floatToSortableInt(maxVal);
+    return numericDocValuesRangeQuery(sf.getName(), minBits, maxBits, true, true, true);
   }
   
   public static Query numericDocValuesRangeQuery(

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
index 2a60343..8c93b52 100644
--- a/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
@@ -25,12 +25,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import com.carrotsearch.hppc.FloatArrayList;
-import com.carrotsearch.hppc.IntArrayList;
-import com.carrotsearch.hppc.IntIntHashMap;
-import com.carrotsearch.hppc.IntLongHashMap;
-import com.carrotsearch.hppc.cursors.IntIntCursor;
-import com.carrotsearch.hppc.cursors.IntLongCursor;
 import org.apache.commons.lang.StringUtils;
 import org.apache.lucene.codecs.DocValuesProducer;
 import org.apache.lucene.index.DocValues;
@@ -43,6 +37,7 @@ import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
 import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.queries.function.FunctionQuery;
 import org.apache.lucene.queries.function.FunctionValues;
@@ -69,10 +64,17 @@ import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.schema.FieldType;
-import org.apache.solr.schema.StrField;
 import org.apache.solr.schema.NumberType;
+import org.apache.solr.schema.StrField;
 import org.apache.solr.uninverting.UninvertingReader;
 
+import com.carrotsearch.hppc.FloatArrayList;
+import com.carrotsearch.hppc.IntArrayList;
+import com.carrotsearch.hppc.IntIntHashMap;
+import com.carrotsearch.hppc.IntLongHashMap;
+import com.carrotsearch.hppc.cursors.IntIntCursor;
+import com.carrotsearch.hppc.cursors.IntLongCursor;
+
 import static org.apache.solr.common.params.CommonParams.SORT;
 
 /**
@@ -474,7 +476,7 @@ public class CollapsingQParserPlugin extends QParserPlugin {
     private final DocValuesProducer collapseValuesProducer;
     private FixedBitSet collapsedSet;
     private SortedDocValues collapseValues;
-    private MultiDocValues.OrdinalMap ordinalMap;
+    private OrdinalMap ordinalMap;
     private SortedDocValues segmentValues;
     private LongValues segmentOrdinalMap;
     private MultiDocValues.MultiSortedDocValues multiSortedDocValues;
@@ -920,7 +922,7 @@ public class CollapsingQParserPlugin extends QParserPlugin {
     private LeafReaderContext[] contexts;
     private DocValuesProducer collapseValuesProducer;
     private SortedDocValues collapseValues;
-    protected MultiDocValues.OrdinalMap ordinalMap;
+    protected OrdinalMap ordinalMap;
     protected SortedDocValues segmentValues;
     protected LongValues segmentOrdinalMap;
     protected MultiDocValues.MultiSortedDocValues multiSortedDocValues;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArrayDV.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArrayDV.java b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArrayDV.java
index 1481f18..fe7a3f2 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArrayDV.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetFieldProcessorByArrayDV.java
@@ -23,6 +23,7 @@ import java.util.List;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.search.DocIdSet;
@@ -43,7 +44,7 @@ class FacetFieldProcessorByArrayDV extends FacetFieldProcessorByArray {
 
   boolean multiValuedField;
   SortedSetDocValues si;  // only used for term lookups (for both single and multi-valued)
-  MultiDocValues.OrdinalMap ordinalMap = null; // maps per-segment ords to global ords
+  OrdinalMap ordinalMap = null; // maps per-segment ords to global ords
 
   FacetFieldProcessorByArrayDV(FacetContext fcontext, FacetField freq, SchemaField sf) {
     super(fcontext, freq, sf);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java b/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java
index 2c37863..a6d6b97 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/MinMaxAgg.java
@@ -21,6 +21,7 @@ import java.util.Arrays;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.util.BytesRef;
@@ -176,7 +177,7 @@ public class MinMaxAgg extends SimpleAggValueSource {
   class SingleValuedOrdAcc extends OrdAcc {
     SortedDocValues topLevel;
     SortedDocValues[] subDvs;
-    MultiDocValues.OrdinalMap ordMap;
+    OrdinalMap ordMap;
     LongValues toGlobal;
     SortedDocValues subDv;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java
index dba410a..4541975 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueAgg.java
@@ -29,6 +29,8 @@ import org.apache.lucene.index.SortedNumericDocValues;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.util.LongIterator;
+import org.apache.solr.util.LongSet;
 
 public class UniqueAgg extends StrAggValueSource {
   public static String UNIQUE = "unique";
@@ -122,75 +124,6 @@ public class UniqueAgg extends StrAggValueSource {
   }
 
 
-
-  static class LongSet {
-
-    static final float LOAD_FACTOR = 0.7f;
-
-    long[] vals;
-    int cardinality;
-    int mask;
-    int threshold;
-    int zeroCount;  // 1 if a 0 was collected
-
-    /** sz must be a power of two */
-    LongSet(int sz) {
-      vals = new long[sz];
-      mask = sz - 1;
-      threshold = (int) (sz * LOAD_FACTOR);
-    }
-
-    void add(long val) {
-      if (val == 0) {
-        zeroCount = 1;
-        return;
-      }
-      if (cardinality >= threshold) {
-        rehash();
-      }
-      
-      // For floats: exponent bits start at bit 23 for single precision,
-      // and bit 52 for double precision.
-      // Many values will only have significant bits just to the right of that,
-      // and the leftmost bits will all be zero.
-
-      // For now, lets just settle to get first 8 significant mantissa bits of double or float in the lowest bits of our hash
-      // The upper bits of our hash will be irrelevant.
-      int h = (int) (val + (val >>> 44) + (val >>> 15));
-      for (int slot = h & mask; ;slot = (slot + 1) & mask) {
-        long v = vals[slot];
-        if (v == 0) {
-          vals[slot] = val;
-          cardinality++;
-          break;
-        } else if (v == val) {
-          // val is already in the set
-          break;
-        }
-      }
-    }
-
-    private void rehash() {
-      long[] oldVals = vals;
-      int newCapacity = vals.length << 1;
-      vals = new long[newCapacity];
-      mask = newCapacity - 1;
-      threshold = (int) (newCapacity * LOAD_FACTOR);
-      cardinality = 0;
-
-      for (long val : oldVals) {
-        if (val != 0) {
-          add(val);
-        }
-      }
-    }
-
-    int cardinality() {
-      return cardinality + zeroCount;
-    }
-  }
-
-
   static abstract class BaseNumericAcc extends SlotAcc {
     SchemaField sf;
     LongSet[] sets;
@@ -259,16 +192,11 @@ public class UniqueAgg extends StrAggValueSource {
       if (unique <= maxExplicit) {
         List lst = new ArrayList( Math.min(unique, maxExplicit) );
         if (set != null) {
-          if (set.zeroCount > 0) {
-            lst.add(0);
-          }
-          for (long val : set.vals) {
-            if (val != 0) {
-              lst.add(val);
-            }
+          LongIterator iter = set.iterator();
+          while (iter.hasNext()) {
+            lst.add( iter.next() );
           }
         }
-
         map.add("vals", lst);
       }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java
index 65fa81a..0a6eb22 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueMultiDvSlotAcc.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.FixedBitSet;
@@ -30,7 +31,7 @@ import org.apache.solr.schema.SchemaField;
 class UniqueMultiDvSlotAcc extends UniqueSlotAcc {
   SortedSetDocValues topLevel;
   SortedSetDocValues[] subDvs;
-  MultiDocValues.OrdinalMap ordMap;
+  OrdinalMap ordMap;
   LongValues toGlobal;
   SortedSetDocValues subDv;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java b/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java
index b39f282..434e680 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/UniqueSinglevaluedSlotAcc.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.FixedBitSet;
@@ -31,7 +32,7 @@ import org.apache.solr.search.SolrIndexSearcher;
 class UniqueSinglevaluedSlotAcc extends UniqueSlotAcc {
   SortedDocValues topLevel;
   SortedDocValues[] subDvs;
-  MultiDocValues.OrdinalMap ordMap;
+  OrdinalMap ordMap;
   LongValues toGlobal;
   SortedDocValues subDv;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java
index 141b095..703307c 100644
--- a/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java
+++ b/solr/core/src/java/org/apache/solr/search/join/BlockJoinFieldFacetAccumulator.java
@@ -21,8 +21,8 @@ import java.util.Arrays;
 
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.MultiDocValues.OrdinalMap;
 import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.OrdinalMap;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
 import org.apache.lucene.util.ArrayUtil;
@@ -50,7 +50,7 @@ class BlockJoinFieldFacetAccumulator {
   // elems are : facet value counter<<32 | last parent doc num 
   private long[] segmentAccums = new long[0];
   // for mapping per-segment ords to global ones
-  private MultiDocValues.OrdinalMap ordinalMap;
+  private OrdinalMap ordinalMap;
   private SchemaField schemaField;
   private SortedDocValues segmentSDV;
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/join/GraphQuery.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/join/GraphQuery.java b/solr/core/src/java/org/apache/solr/search/join/GraphQuery.java
index db41651..7e52f0c 100644
--- a/solr/core/src/java/org/apache/solr/search/join/GraphQuery.java
+++ b/solr/core/src/java/org/apache/solr/search/join/GraphQuery.java
@@ -25,16 +25,15 @@ import java.util.TreeSet;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.AutomatonQuery;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.lucene.search.DocValuesFieldExistsQuery;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.TermInSetQuery;
 import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.WildcardQuery;
 import org.apache.lucene.util.BytesRef;
@@ -42,6 +41,7 @@ import org.apache.lucene.util.BytesRefHash;
 import org.apache.lucene.util.FixedBitSet;
 import org.apache.lucene.util.automaton.Automaton;
 import org.apache.lucene.util.automaton.DaciukMihovAutomatonBuilder;
+import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.BitDocSet;
 import org.apache.solr.search.DocSet;
 import org.apache.solr.search.Filter;
@@ -130,17 +130,22 @@ public class GraphQuery extends Query {
   protected class GraphQueryWeight extends Weight {
     
     final SolrIndexSearcher fromSearcher;
-    private final float boost;
-    private int frontierSize = 0;
     private int currentDepth = -1;
     private Filter filter;
     private DocSet resultSet;
-    
+    SchemaField fromSchemaField;
+    SchemaField toSchemaField;
+
     public GraphQueryWeight(SolrIndexSearcher searcher, float boost) {
       // Grab the searcher so we can run additional searches.
       super(null);
       this.fromSearcher = searcher;
-      this.boost = boost;
+      this.fromSchemaField = searcher.getSchema().getField(fromField);
+      this.toSchemaField = searcher.getSchema().getField(toField);
+    }
+
+    GraphQuery getGraphQuery() {
+      return GraphQuery.this;
     }
     
     @Override
@@ -175,7 +180,7 @@ public class GraphQuery extends Query {
       // the initial query for the frontier for the first query
       Query frontierQuery = q;
       // Find all documents in this graph that are leaf nodes to speed traversal
-      DocSet leafNodes = resolveLeafNodes(toField);
+      DocSet leafNodes = resolveLeafNodes();
       // Start the breadth first graph traversal.
       
       do {
@@ -187,25 +192,17 @@ public class GraphQuery extends Query {
           // if we've reached the max depth, don't worry about collecting edges.
           fromSet = fromSearcher.getDocSetBits(frontierQuery);
           // explicitly the frontier size is zero now so we can break
-          frontierSize = 0;
+          frontierQuery = null;
         } else {
           // when we're not at the max depth level, we need to collect edges          
           // Create the graph result collector for this level
-          GraphTermsCollector graphResultCollector = new GraphTermsCollector(toField,capacity, resultBits, leafNodes);
+          GraphEdgeCollector graphResultCollector = toSchemaField.getType().isPointField()
+              ? new GraphPointsCollector(this, capacity, resultBits, leafNodes)
+              : new GraphTermsCollector(this, capacity, resultBits, leafNodes);
+
           fromSearcher.search(frontierQuery, graphResultCollector);
           fromSet = graphResultCollector.getDocSet();
-          // All edge ids on the frontier.
-          BytesRefHash collectorTerms = graphResultCollector.getCollectorTerms();
-          frontierSize = collectorTerms.size();
-          // The resulting doc set from the frontier.
-          FrontierQuery fq = buildFrontierQuery(collectorTerms, frontierSize);
-          if (fq == null) {
-            // in case we get null back, make sure we know we're done at this level.
-            frontierSize = 0;
-          } else {
-            frontierQuery = fq.getQuery();
-            frontierSize = fq.getFrontierSize();
-          }
+          frontierQuery = graphResultCollector.getFrontierQuery();
         }
         if (currentDepth == 0 && !returnRoot) {
           // grab a copy of the root bits but only if we need it.
@@ -217,7 +214,7 @@ public class GraphQuery extends Query {
         if ((maxDepth != -1 && currentDepth >= maxDepth)) {
           break;
         }
-      } while (frontierSize > 0);
+      } while (frontierQuery != null);
       // helper bit set operations on the final result set
       if (!returnRoot) {
         resultBits.andNot(rootBits);
@@ -232,9 +229,10 @@ public class GraphQuery extends Query {
       }
     }
     
-    private DocSet resolveLeafNodes(String field) throws IOException {
+    private DocSet resolveLeafNodes() throws IOException {
+      String field = toSchemaField.getName();
       BooleanQuery.Builder leafNodeQuery = new BooleanQuery.Builder();
-      WildcardQuery edgeQuery = new WildcardQuery(new Term(field, "*"));
+      Query edgeQuery = toSchemaField.hasDocValues() ? new DocValuesFieldExistsQuery(field) : new WildcardQuery(new Term(field, "*"));
       leafNodeQuery.add(edgeQuery, Occur.MUST_NOT);
       DocSet leafNodes = fromSearcher.getDocSet(leafNodeQuery.build());
       return leafNodes;
@@ -252,50 +250,7 @@ public class GraphQuery extends Query {
       final Automaton a = DaciukMihovAutomatonBuilder.build(terms);
       return a;    
     }
-    
-    /**
-     * This return a query that represents the documents that match the next hop in the query.
-     * 
-     * collectorTerms - the terms that represent the edge ids for the current frontier.
-     * frontierSize - the size of the frontier query (number of unique edges)
-     *  
-     */
-    public FrontierQuery buildFrontierQuery(BytesRefHash collectorTerms, Integer frontierSize) {
-      if (collectorTerms == null || collectorTerms.size() == 0) {
-        // return null if there are no terms (edges) to traverse.
-        return null;
-      } else {
-        // Create a query
-        Query q = null;
 
-        // TODO: see if we should dynamically select this based on the frontier size.
-        if (useAutn) {
-          // build an automaton based query for the frontier.
-          Automaton autn = buildAutomaton(collectorTerms);
-          AutomatonQuery autnQuery = new AutomatonQuery(new Term(fromField), autn);
-          q = autnQuery;
-        } else {
-          List<BytesRef> termList = new ArrayList<>(collectorTerms.size());
-          for (int i = 0 ; i < collectorTerms.size(); i++) {
-            BytesRef ref = new BytesRef();
-            collectorTerms.get(i, ref);
-            termList.add(ref);
-          }
-          q = new TermInSetQuery(fromField, termList);
-        }
-        
-        // If there is a filter to be used while crawling the graph, add that.
-        if (traversalFilter != null) {
-          BooleanQuery.Builder builder = new BooleanQuery.Builder();
-          builder.add(q, Occur.MUST);
-          builder.add(traversalFilter, Occur.MUST);
-          q = builder.build();
-        } 
-        // return the new query. 
-        FrontierQuery frontier = new FrontierQuery(q, frontierSize);
-        return frontier;
-      }
-    }
     
     @Override
     public Scorer scorer(LeafReaderContext context) throws IOException {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/join/GraphQueryParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/join/GraphQueryParser.java b/solr/core/src/java/org/apache/solr/search/join/GraphQueryParser.java
index 0ef9e6c..9c9b852 100644
--- a/solr/core/src/java/org/apache/solr/search/join/GraphQueryParser.java
+++ b/solr/core/src/java/org/apache/solr/search/join/GraphQueryParser.java
@@ -41,6 +41,7 @@ public class GraphQueryParser extends QParser {
     String traversalFilterS = localParams.get("traversalFilter");
     Query traversalFilter = traversalFilterS == null ? null : subQuery(traversalFilterS, null).getQuery();
 
+    // NOTE: the from/to are reversed from {!join}
     String fromField = localParams.get("from", "node_id");
     String toField = localParams.get("to", "edge_ids");
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8d00e53b/solr/core/src/java/org/apache/solr/search/join/GraphTermsCollector.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/join/GraphTermsCollector.java b/solr/core/src/java/org/apache/solr/search/join/GraphTermsCollector.java
index 377f71b..f32c83b 100644
--- a/solr/core/src/java/org/apache/solr/search/join/GraphTermsCollector.java
+++ b/solr/core/src/java/org/apache/solr/search/join/GraphTermsCollector.java
@@ -17,19 +17,40 @@
 package org.apache.solr.search.join;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
 
+import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
 import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.AutomatonQuery;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Collector;
+import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SimpleCollector;
+import org.apache.lucene.search.TermInSetQuery;
 import org.apache.lucene.util.BitSet;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefHash;
 import org.apache.lucene.util.FixedBitSet;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.lucene.util.automaton.Automaton;
+import org.apache.lucene.util.automaton.DaciukMihovAutomatonBuilder;
+import org.apache.solr.schema.NumberType;
+import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.BitDocSet;
 import org.apache.solr.search.DocSet;
+import org.apache.solr.util.LongIterator;
+import org.apache.solr.util.LongSet;
 
 /**
  * A graph hit collector.  This accumulates the edges for a given graph traversal.
@@ -37,17 +58,14 @@ import org.apache.solr.search.DocSet;
  * already traversed.
  * @lucene.internal
  */
-class GraphTermsCollector extends SimpleCollector implements Collector {
-  
-  // the field to collect edge ids from
-  private String field;
-  // all the collected terms
-  private BytesRefHash collectorTerms;
-  private SortedSetDocValues docTermOrds;
+abstract class GraphEdgeCollector extends SimpleCollector implements Collector {
+
+  GraphQuery.GraphQueryWeight weight;
+
   // the result set that is being collected.
-  private Bits currentResult;
+  Bits currentResult;
   // known leaf nodes
-  private DocSet leafNodes;
+  DocSet leafNodes;
   // number of hits discovered at this level.
   int numHits=0;
   BitSet bits;
@@ -56,11 +74,10 @@ class GraphTermsCollector extends SimpleCollector implements Collector {
   int baseInParent;
   // if we care to track this.
   boolean hasCycles = false;
-  
-  GraphTermsCollector(String field,int maxDoc, Bits currentResult, DocSet leafNodes) {
-    this.field = field;
+
+  GraphEdgeCollector(GraphQuery.GraphQueryWeight weight, int maxDoc, Bits currentResult, DocSet leafNodes) {
+    this.weight = weight;
     this.maxDoc = maxDoc;
-    this.collectorTerms =  new BytesRefHash();
     this.currentResult = currentResult;
     this.leafNodes = leafNodes;
     if (bits==null) {
@@ -80,29 +97,14 @@ class GraphTermsCollector extends SimpleCollector implements Collector {
     // collect the docs
     addDocToResult(doc);
     // Optimization to not look up edges for a document that is a leaf node
-    if (!leafNodes.exists(doc)) {
+    if (leafNodes == null || !leafNodes.exists(doc)) {
       addEdgeIdsToResult(doc-base);
     } 
     // Note: tracking links in for each result would be a huge memory hog... so not implementing at this time.
     
   }
   
-  private void addEdgeIdsToResult(int doc) throws IOException {
-    // set the doc to pull the edges ids for.
-    if (doc > docTermOrds.docID()) {
-      docTermOrds.advance(doc);
-    }
-    if (doc == docTermOrds.docID()) {
-      BytesRef edgeValue = new BytesRef();
-      long ord;
-      while ((ord = docTermOrds.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
-        // TODO: handle non string type fields.
-        edgeValue = docTermOrds.lookupOrd(ord);
-        // add the edge id to the collector terms.
-        collectorTerms.add(edgeValue);
-      }
-    }
-  }
+  abstract void addEdgeIdsToResult(int doc) throws IOException;
   
   private void addDocToResult(int docWithBase) {
     // this document is part of the traversal. mark it in our bitmap.
@@ -121,14 +123,25 @@ class GraphTermsCollector extends SimpleCollector implements Collector {
   
   @Override
   public void doSetNextReader(LeafReaderContext context) throws IOException {
-    // Grab the updated doc values.
-    docTermOrds = DocValues.getSortedSet(context.reader(), field);
     base = context.docBase;
     baseInParent = context.docBaseInParent;
   }
-  
-  public BytesRefHash getCollectorTerms() {
-    return collectorTerms;
+
+  protected abstract Query getResultQuery();
+
+  public Query getFrontierQuery() {
+    Query q = getResultQuery();
+    if (q == null) return null;
+
+    // If there is a filter to be used while crawling the graph, add that.
+    if (weight.getGraphQuery().getTraversalFilter() != null) {
+      BooleanQuery.Builder builder = new BooleanQuery.Builder();
+      builder.add(q, BooleanClause.Occur.MUST);
+      builder.add(weight.getGraphQuery().getTraversalFilter(), BooleanClause.Occur.MUST);
+      q = builder.build();
+    }
+
+    return q;
   }
   
   @Override
@@ -137,3 +150,180 @@ class GraphTermsCollector extends SimpleCollector implements Collector {
   }
   
 }
+
+class GraphTermsCollector extends GraphEdgeCollector {
+  // all the collected terms
+  private BytesRefHash collectorTerms;
+  private SortedSetDocValues docTermOrds;
+
+
+  GraphTermsCollector(GraphQuery.GraphQueryWeight weight, int maxDoc, Bits currentResult, DocSet leafNodes) {
+    super(weight, maxDoc, currentResult, leafNodes);
+    this.collectorTerms =  new BytesRefHash();
+  }
+
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    super.doSetNextReader(context);
+    // Grab the updated doc values.
+    docTermOrds = DocValues.getSortedSet(context.reader(), weight.getGraphQuery().getToField());
+  }
+
+  @Override
+  void addEdgeIdsToResult(int doc) throws IOException {
+    // set the doc to pull the edges ids for.
+    if (doc > docTermOrds.docID()) {
+      docTermOrds.advance(doc);
+    }
+    if (doc == docTermOrds.docID()) {
+      BytesRef edgeValue = new BytesRef();
+      long ord;
+      while ((ord = docTermOrds.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+        edgeValue = docTermOrds.lookupOrd(ord);
+        // add the edge id to the collector terms.
+        collectorTerms.add(edgeValue);
+      }
+    }
+  }
+
+  @Override
+  protected Query getResultQuery() {
+    if (collectorTerms == null || collectorTerms.size() == 0) {
+      // return null if there are no terms (edges) to traverse.
+      return null;
+    } else {
+      // Create a query
+      Query q = null;
+
+      GraphQuery gq = weight.getGraphQuery();
+      // TODO: see if we should dynamically select this based on the frontier size.
+      if (gq.isUseAutn()) {
+        // build an automaton based query for the frontier.
+        Automaton autn = buildAutomaton(collectorTerms);
+        AutomatonQuery autnQuery = new AutomatonQuery(new Term(gq.getFromField()), autn);
+        q = autnQuery;
+      } else {
+        List<BytesRef> termList = new ArrayList<>(collectorTerms.size());
+        for (int i = 0 ; i < collectorTerms.size(); i++) {
+          BytesRef ref = new BytesRef();
+          collectorTerms.get(i, ref);
+          termList.add(ref);
+        }
+        q = new TermInSetQuery(gq.getFromField(), termList);
+      }
+
+      return q;
+    }
+  }
+
+
+  /** Build an automaton to represent the frontier query */
+  private Automaton buildAutomaton(BytesRefHash termBytesHash) {
+    // need top pass a sorted set of terms to the autn builder (maybe a better way to avoid this?)
+    final TreeSet<BytesRef> terms = new TreeSet<BytesRef>();
+    for (int i = 0 ; i < termBytesHash.size(); i++) {
+      BytesRef ref = new BytesRef();
+      termBytesHash.get(i, ref);
+      terms.add(ref);
+    }
+    final Automaton a = DaciukMihovAutomatonBuilder.build(terms);
+    return a;
+  }
+}
+
+
+class GraphPointsCollector extends GraphEdgeCollector {
+  final LongSet set = new LongSet(256);
+
+  SortedNumericDocValues values = null;
+
+  GraphPointsCollector(GraphQuery.GraphQueryWeight weight, int maxDoc, Bits currentResult, DocSet leafNodes) {
+    super(weight, maxDoc, currentResult, leafNodes);
+  }
+
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    super.doSetNextReader(context);
+    values = DocValues.getSortedNumeric(context.reader(), weight.getGraphQuery().getToField());
+  }
+
+  @Override
+  void addEdgeIdsToResult(int doc) throws IOException {
+    // set the doc to pull the edges ids for.
+    int valuesDoc = values.docID();
+    if (valuesDoc < doc) {
+      valuesDoc = values.advance(doc);
+    }
+    if (valuesDoc == doc) {
+      int count = values.docValueCount();
+      for (int i = 0; i < count; i++) {
+        long v = values.nextValue();
+        set.add(v);
+      }
+    }
+  }
+
+  @Override
+  protected Query getResultQuery() {
+    if (set.cardinality() == 0) return null;
+
+    Query q = null;
+    SchemaField sfield = weight.fromSchemaField;
+    NumberType ntype = sfield.getType().getNumberType();
+    boolean multiValued = sfield.multiValued();
+
+    if (ntype == NumberType.LONG || ntype == NumberType.DATE) {
+      long[] vals = new long[set.cardinality()];
+      int i = 0;
+      for (LongIterator iter = set.iterator(); iter.hasNext(); ) {
+        long bits = iter.next();
+        long v = bits;
+        vals[i++] = v;
+      }
+      q = LongPoint.newSetQuery(sfield.getName(), vals);
+    } else if (ntype == NumberType.INTEGER) {
+      int[] vals = new int[set.cardinality()];
+      int i = 0;
+      for (LongIterator iter = set.iterator(); iter.hasNext(); ) {
+        long bits = iter.next();
+        int v = (int)bits;
+        vals[i++] = v;
+      }
+      q = IntPoint.newSetQuery(sfield.getName(), vals);
+    } else if (ntype == NumberType.DOUBLE) {
+      double[] vals = new double[set.cardinality()];
+      int i = 0;
+      for (LongIterator iter = set.iterator(); iter.hasNext(); ) {
+        long bits = iter.next();
+        double v = multiValued ? NumericUtils.sortableLongToDouble(bits) : Double.longBitsToDouble(bits);
+        vals[i++] = v;
+      }
+      q = DoublePoint.newSetQuery(sfield.getName(), vals);
+    } else if (ntype == NumberType.FLOAT) {
+      float[] vals = new float[set.cardinality()];
+      int i = 0;
+      for (LongIterator iter = set.iterator(); iter.hasNext(); ) {
+        long bits = iter.next();
+        float v = multiValued ? NumericUtils.sortableIntToFloat((int) bits) : Float.intBitsToFloat((int) bits);
+        vals[i++] = v;
+      }
+      q = FloatPoint.newSetQuery(sfield.getName(), vals);
+    }
+
+    return q;
+  }
+
+
+  /** Build an automaton to represent the frontier query */
+  private Automaton buildAutomaton(BytesRefHash termBytesHash) {
+    // need top pass a sorted set of terms to the autn builder (maybe a better way to avoid this?)
+    final TreeSet<BytesRef> terms = new TreeSet<BytesRef>();
+    for (int i = 0 ; i < termBytesHash.size(); i++) {
+      BytesRef ref = new BytesRef();
+      termBytesHash.get(i, ref);
+      terms.add(ref);
+    }
+    final Automaton a = DaciukMihovAutomatonBuilder.build(terms);
+    return a;
+  }
+}