From fea4e40233eee743a026d1bf2820f7f47875d7a0 Mon Sep 17 00:00:00 2001
From: Mike Drob <mdrob@cloudera.com>
Date: Mon, 9 Feb 2015 12:23:50 -0600
Subject: [PATCH] LUCENE-6232 Add QueryContext class

Replace all occurances of raw Map coming from ValueSource with the new
QueryContext class. This class features a get(Object) and
put(Object,Object) which are admittedly unsafe, but may help the
transition. In addition, there are typesafe methods for storing scorers
and searchers.
---
 .../lucene/expressions/ExpressionComparator.java   |   5 +-
 .../lucene/expressions/ExpressionRescorer.java     |   5 +-
 .../lucene/expressions/ExpressionValueSource.java  |   5 +-
 .../lucene/expressions/ScoreValueSource.java       |   7 +-
 .../expressions/TestExpressionValueSource.java     |   5 +-
 .../org/apache/lucene/facet/range/DoubleRange.java |   3 +-
 .../lucene/facet/range/DoubleRangeFacetCounts.java |   3 +-
 .../org/apache/lucene/facet/range/LongRange.java   |   3 +-
 .../lucene/facet/range/LongRangeFacetCounts.java   |   3 +-
 .../taxonomy/TaxonomyFacetSumValueSource.java      |   9 +-
 .../lucene/facet/range/TestRangeFacetCounts.java   |  10 +-
 .../taxonomy/TestTaxonomyFacetSumValueSource.java  |   7 +-
 .../lucene/search/grouping/GroupingSearch.java     |  20 ++--
 .../function/FunctionAllGroupHeadsCollector.java   |   9 +-
 .../function/FunctionAllGroupsCollector.java       |  16 +--
 .../function/FunctionDistinctValuesCollector.java  |   5 +-
 .../FunctionFirstPassGroupingCollector.java        |   9 +-
 .../FunctionSecondPassGroupingCollector.java       |  18 ++--
 .../grouping/AllGroupHeadsCollectorTest.java       |   3 +-
 .../search/grouping/AllGroupsCollectorTest.java    |   5 +-
 .../grouping/DistinctValuesCollectorTest.java      |   5 +-
 .../lucene/search/grouping/GroupingSearchTest.java |   3 +-
 .../lucene/search/grouping/TestGrouping.java       |  11 ++-
 .../lucene/queries/function/BoostedQuery.java      |   4 +-
 .../lucene/queries/function/FunctionQuery.java     |   3 +-
 .../lucene/queries/function/ValueSource.java       |  25 +++--
 .../function/valuesource/BytesRefFieldSource.java  |   2 +-
 .../function/valuesource/ConstValueSource.java     |   7 +-
 .../queries/function/valuesource/DefFunction.java  |   9 +-
 .../function/valuesource/DocFreqValueSource.java   |   8 +-
 .../valuesource/DoubleConstValueSource.java        |   7 +-
 .../function/valuesource/DoubleFieldSource.java    |   6 +-
 .../function/valuesource/DualFloatFunction.java    |   4 +-
 .../function/valuesource/EnumFieldSource.java      |   2 +-
 .../function/valuesource/FloatFieldSource.java     |   2 +-
 .../function/valuesource/IDFValueSource.java       |   4 +-
 .../queries/function/valuesource/IfFunction.java   |   4 +-
 .../function/valuesource/IntFieldSource.java       |   2 +-
 .../valuesource/JoinDocFreqValueSource.java        |   2 +-
 .../function/valuesource/LinearFloatFunction.java  |   4 +-
 .../function/valuesource/LiteralValueSource.java   |   2 +-
 .../function/valuesource/LongFieldSource.java      |   2 +-
 .../function/valuesource/MaxDocValueSource.java    |   8 +-
 .../function/valuesource/MultiBoolFunction.java    |   4 +-
 .../function/valuesource/MultiFloatFunction.java   |   4 +-
 .../function/valuesource/MultiFunction.java        |   4 +-
 .../function/valuesource/NormValueSource.java      |   8 +-
 .../function/valuesource/NumDocsValueSource.java   |   2 +-
 .../queries/function/valuesource/QueryContext.java | 108 +++++++++++++++++++++
 .../function/valuesource/QueryValueSource.java     |  22 ++---
 .../valuesource/RangeMapFloatFunction.java         |   4 +-
 .../valuesource/ReciprocalFloatFunction.java       |   9 +-
 .../function/valuesource/ScaleFloatFunction.java   |   6 +-
 .../function/valuesource/SimpleBoolFunction.java   |   9 +-
 .../function/valuesource/SimpleFloatFunction.java  |   2 +-
 .../function/valuesource/SingleFunction.java       |   7 +-
 .../function/valuesource/SortedSetFieldSource.java |   2 +-
 .../valuesource/SumTotalTermFreqValueSource.java   |   4 +-
 .../function/valuesource/TFValueSource.java        |   4 +-
 .../function/valuesource/TermFreqValueSource.java  |   2 +-
 .../valuesource/TotalTermFreqValueSource.java      |   4 +-
 .../function/valuesource/VectorValueSource.java    |  11 +--
 .../queries/function/TestSortedSetFieldSource.java |   3 +-
 .../lucene/queries/function/TestValueSources.java  |  13 +--
 .../spatial/bbox/BBoxSimilarityValueSource.java    |  11 ++-
 .../lucene/spatial/bbox/BBoxValueSource.java       |  11 ++-
 .../spatial/serialized/SerializedDVStrategy.java   |  26 ++---
 .../spatial/util/CachingDoubleValueSource.java     |  11 ++-
 .../spatial/util/DistanceToShapeValueSource.java   |  17 ++--
 .../lucene/spatial/util/ShapeAreaValueSource.java  |  11 ++-
 .../util/ShapeFieldCacheDistanceValueSource.java   |   4 +-
 .../spatial/util/ShapePredicateValueSource.java    |  11 ++-
 .../lucene/spatial/vector/DistanceValueSource.java |  13 +--
 .../suggest/DocumentValueSourceDictionary.java     |   8 +-
 .../util/valuesource/ConstDateSource.java          |   4 +-
 .../util/valuesource/ConstDoubleSource.java        |   4 +-
 .../util/valuesource/DateFieldSource.java          |   3 +-
 .../util/valuesource/DualDoubleFunction.java       |   5 +-
 .../util/valuesource/FilterFieldSource.java        |   3 +-
 .../util/valuesource/MultiDateFunction.java        |   3 +-
 .../util/valuesource/MultiDoubleFunction.java      |   6 +-
 .../util/valuesource/MultiStringFunction.java      |   3 +-
 .../util/valuesource/SingleDoubleFunction.java     |   3 +-
 .../util/valuesource/SingleStringFunction.java     |   3 +-
 .../solr/handler/component/FieldFacetStats.java    |   3 +-
 .../solr/handler/component/StatsValuesFactory.java |   3 +-
 .../org/apache/solr/request/NumericFacets.java     |   7 +-
 .../response/transform/ValueSourceAugmenter.java   |   3 +-
 .../src/java/org/apache/solr/schema/BoolField.java |   6 +-
 .../java/org/apache/solr/schema/CurrencyField.java |   5 +-
 .../java/org/apache/solr/schema/LatLonType.java    |   6 +-
 .../org/apache/solr/schema/RandomSortField.java    |   3 +-
 .../org/apache/solr/schema/StrFieldSource.java     |   3 +-
 .../solr/search/CollapsingQParserPlugin.java       |  10 +-
 .../org/apache/solr/search/FunctionRangeQuery.java |   9 +-
 .../src/java/org/apache/solr/search/Grouping.java  |   4 +-
 .../apache/solr/search/SolrConstantScoreQuery.java |   3 +-
 .../java/org/apache/solr/search/SolrFilter.java    |  12 +--
 .../org/apache/solr/search/ValueSourceParser.java  |  14 +--
 .../search/function/CollapseScoreFunction.java     |   6 +-
 .../solr/search/function/FileFloatSource.java      |   3 +-
 .../solr/search/function/OrdFieldSource.java       |   6 +-
 .../search/function/ReverseOrdFieldSource.java     |   6 +-
 .../search/function/ValueSourceRangeFilter.java    |   5 +-
 .../search/function/distance/GeohashFunction.java  |   4 +-
 .../distance/GeohashHaversineFunction.java         |   6 +-
 .../function/distance/HaversineConstFunction.java  |   6 +-
 .../function/distance/HaversineFunction.java       |   7 +-
 .../function/distance/StringDistanceFunction.java  |   3 +-
 .../function/distance/VectorDistanceFunction.java  |   5 +-
 .../solr/search/grouping/CommandHandler.java       |   5 +-
 .../command/SearchGroupsFieldCommand.java          |   5 +-
 .../distributed/command/TopGroupsFieldCommand.java |   3 +-
 .../java/org/apache/solr/update/VersionInfo.java   |   3 +-
 ...DocBasedVersionConstraintsProcessorFactory.java |   3 +-
 .../solr/core/CountUsageValueSourceParser.java     |   3 +-
 .../org/apache/solr/search/TestIndexSearcher.java  |   3 +-
 117 files changed, 505 insertions(+), 336 deletions(-)
 create mode 100644 lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryContext.java

diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionComparator.java b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionComparator.java
index bf386bc..b42fb51 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionComparator.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionComparator.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.FieldComparator;
 import org.apache.lucene.search.LeafFieldComparator;
 import org.apache.lucene.search.Scorer;
@@ -48,9 +49,9 @@ class ExpressionComparator extends FieldComparator<Double> implements LeafFieldC
     // TODO: might be cleaner to lazy-init 'source' and set scorer after?
     assert readerContext != null;
     try {
-      Map<String,Object> context = new HashMap<>();
+      QueryContext context = new QueryContext();
       assert scorer != null;
-      context.put("scorer", scorer);
+      context.setScorer(scorer);
       scores = source.getValues(context, readerContext);
     } catch (IOException e) {
       throw new RuntimeException(e);
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java
index 884dea7..eda49cc 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java
@@ -25,6 +25,7 @@ import java.util.Map;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Rescorer;
@@ -63,13 +64,13 @@ class ExpressionRescorer extends SortRescorer {
     int subReader = ReaderUtil.subIndex(docID, leaves);
     LeafReaderContext readerContext = leaves.get(subReader);
     int docIDInSegment = docID - readerContext.docBase;
-    Map<String,Object> context = new HashMap<>();
+    QueryContext context = new QueryContext();
 
     FakeScorer fakeScorer = new FakeScorer();
     fakeScorer.score = firstPassExplanation.getValue();
     fakeScorer.doc = docIDInSegment;
 
-    context.put("scorer", fakeScorer);
+    context.setScorer(fakeScorer);
 
     for(String variable : expression.variables) {
       result.addDetail(new Explanation((float) bindings.getValueSource(variable).getValues(context, readerContext).doubleVal(docIDInSegment),
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
index 5839796..9b1cce4 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.SortField;
 
 /**
@@ -58,11 +59,11 @@ final class ExpressionValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     Map<String, FunctionValues> valuesCache = (Map<String, FunctionValues>)context.get("valuesCache");
     if (valuesCache == null) {
       valuesCache = new HashMap<>();
-      context = new HashMap(context);
+      context = new QueryContext(context);
       context.put("valuesCache", valuesCache);
     }
     FunctionValues[] externalValues = new FunctionValues[expression.variables.length];
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/ScoreValueSource.java b/lucene/expressions/src/java/org/apache/lucene/expressions/ScoreValueSource.java
index c6ffb2a..fdb49f3 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/ScoreValueSource.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/ScoreValueSource.java
@@ -20,24 +20,23 @@ package org.apache.lucene.expressions;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Scorer;
 
 import java.io.IOException;
-import java.util.Map;
 
 /**
  * A {@link ValueSource} which uses the {@link Scorer} passed through
  * the context map by {@link ExpressionComparator}.
  */
-@SuppressWarnings({"rawtypes"})
 class ScoreValueSource extends ValueSource {
 
   /**
    * <code>context</code> must contain a key "scorer" which is a {@link Scorer}.
    */
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    Scorer v = (Scorer) context.get("scorer");
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
+    Scorer v = context.getScorer();
     if (v == null) {
       throw new IllegalStateException("Expressions referencing the score can only be used for sorting");
     }
diff --git a/lucene/expressions/src/test/org/apache/lucene/expressions/TestExpressionValueSource.java b/lucene/expressions/src/test/org/apache/lucene/expressions/TestExpressionValueSource.java
index debcb81..fc4717d 100644
--- a/lucene/expressions/src/test/org/apache/lucene/expressions/TestExpressionValueSource.java
+++ b/lucene/expressions/src/test/org/apache/lucene/expressions/TestExpressionValueSource.java
@@ -31,6 +31,7 @@ import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.ValueSourceScorer;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.store.Directory;
@@ -86,7 +87,7 @@ public class TestExpressionValueSource extends LuceneTestCase {
     
     assertEquals(1, reader.leaves().size());
     LeafReaderContext leaf = reader.leaves().get(0);
-    FunctionValues values = vs.getValues(new HashMap<String,Object>(), leaf);
+    FunctionValues values = vs.getValues(new QueryContext(), leaf);
     
     assertEquals(10, values.doubleVal(0), 0);
     assertEquals(10, values.floatVal(0), 0);
@@ -124,7 +125,7 @@ public class TestExpressionValueSource extends LuceneTestCase {
     
     assertEquals(1, reader.leaves().size());
     LeafReaderContext leaf = reader.leaves().get(0);
-    FunctionValues values = vs.getValues(new HashMap<String,Object>(), leaf);
+    FunctionValues values = vs.getValues(new QueryContext(), leaf);
     
     // everything
     ValueSourceScorer scorer = values.getRangeScorer(leaf.reader(), "4", "40", true, true);
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java b/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
index f6e8e3b..9275c8d 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Filter;
@@ -117,7 +118,7 @@ public final class DoubleRange extends Range {
         // ValueSourceRangeFilter (solr); also,
         // https://issues.apache.org/jira/browse/LUCENE-4251
 
-        final FunctionValues values = valueSource.getValues(Collections.emptyMap(), context);
+        final FunctionValues values = valueSource.getValues(new QueryContext(), context);
 
         final int maxDoc = context.reader().maxDoc();
 
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRangeFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRangeFacetCounts.java
index 6610851..9f0fec0 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRangeFacetCounts.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRangeFacetCounts.java
@@ -30,6 +30,7 @@ import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource; // javadocs
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.Filter;
 import org.apache.lucene.util.Bits;
@@ -93,7 +94,7 @@ public class DoubleRangeFacetCounts extends RangeFacetCounts {
 
     int missingCount = 0;
     for (MatchingDocs hits : matchingDocs) {
-      FunctionValues fv = valueSource.getValues(Collections.emptyMap(), hits.context);
+      FunctionValues fv = valueSource.getValues(new QueryContext(), hits.context);
       
       totCount += hits.totalHits;
       Bits bits;
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java b/lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java
index c382012..0c56b68 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/range/LongRange.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Filter;
@@ -109,7 +110,7 @@ public final class LongRange extends Range {
         // ValueSourceRangeFilter (solr); also,
         // https://issues.apache.org/jira/browse/LUCENE-4251
 
-        final FunctionValues values = valueSource.getValues(Collections.emptyMap(), context);
+        final FunctionValues values = valueSource.getValues(new QueryContext(), context);
 
         final int maxDoc = context.reader().maxDoc();
 
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/LongRangeFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/range/LongRangeFacetCounts.java
index 649ba41..242dfe5 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/range/LongRangeFacetCounts.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/range/LongRangeFacetCounts.java
@@ -27,6 +27,7 @@ import org.apache.lucene.facet.FacetsCollector;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.Filter;
 import org.apache.lucene.util.Bits;
@@ -74,7 +75,7 @@ public class LongRangeFacetCounts extends RangeFacetCounts {
 
     int missingCount = 0;
     for (MatchingDocs hits : matchingDocs) {
-      FunctionValues fv = valueSource.getValues(Collections.emptyMap(), hits.context);
+      FunctionValues fv = valueSource.getValues(new QueryContext(), hits.context);
       
       totCount += hits.totalHits;
       Bits bits;
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacetSumValueSource.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacetSumValueSource.java
index bef02b4..45363d4 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacetSumValueSource.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacetSumValueSource.java
@@ -29,6 +29,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.util.IntsRef;
@@ -62,9 +63,9 @@ public class TaxonomyFacetSumValueSource extends FloatTaxonomyFacets {
 
   private final void sumValues(List<MatchingDocs> matchingDocs, boolean keepScores, ValueSource valueSource) throws IOException {
     final FakeScorer scorer = new FakeScorer();
-    Map<String, Scorer> context = new HashMap<>();
+    QueryContext context = new QueryContext();
     if (keepScores) {
-      context.put("scorer", scorer);
+      context.setScorer(scorer);
     }
     IntsRef scratch = new IntsRef();
     for(MatchingDocs hits : matchingDocs) {
@@ -103,8 +104,8 @@ public class TaxonomyFacetSumValueSource extends FloatTaxonomyFacets {
     }
 
     @Override
-    public FunctionValues getValues(@SuppressWarnings("rawtypes") Map context, LeafReaderContext readerContext) throws IOException {
-      final Scorer scorer = (Scorer) context.get("scorer");
+    public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
+      final Scorer scorer = context.getScorer();
       if (scorer == null) {
         throw new IllegalStateException("scores are missing; be sure to pass keepScores=true to FacetsCollector");
       }
diff --git a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
index b825f08..824f86b 100644
--- a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
+++ b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
@@ -31,8 +31,8 @@ import org.apache.lucene.document.FloatField;
 import org.apache.lucene.document.LongField;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.facet.DrillDownQuery;
-import org.apache.lucene.facet.DrillSideways.DrillSidewaysResult;
 import org.apache.lucene.facet.DrillSideways;
+import org.apache.lucene.facet.DrillSideways.DrillSidewaysResult;
 import org.apache.lucene.facet.FacetField;
 import org.apache.lucene.facet.FacetResult;
 import org.apache.lucene.facet.FacetTestCase;
@@ -44,10 +44,10 @@ import org.apache.lucene.facet.MultiFacets;
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
-import org.apache.lucene.index.LeafReader;
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
@@ -55,6 +55,7 @@ import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.CachingWrapperFilter;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
@@ -874,9 +875,8 @@ public class TestRangeFacetCounts extends FacetTestCase {
     writer.forceMerge(1);
 
     final ValueSource vs = new ValueSource() {
-        @SuppressWarnings("rawtypes")
         @Override
-        public FunctionValues getValues(Map ignored, LeafReaderContext ignored2) {
+        public FunctionValues getValues(QueryContext ignored, LeafReaderContext ignored2) {
           return new DoubleDocValues(null) {
             @Override
             public double doubleVal(int doc) {
diff --git a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyFacetSumValueSource.java b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyFacetSumValueSource.java
index 9869446..6b97d6b 100644
--- a/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyFacetSumValueSource.java
+++ b/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyFacetSumValueSource.java
@@ -38,10 +38,10 @@ import org.apache.lucene.facet.FacetsConfig;
 import org.apache.lucene.facet.LabelAndValue;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.FunctionQuery;
@@ -51,6 +51,7 @@ import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
 import org.apache.lucene.queries.function.valuesource.IntFieldSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.ConstantScoreQuery;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MatchAllDocsQuery;
@@ -328,8 +329,8 @@ public class TestTaxonomyFacetSumValueSource extends FacetTestCase {
 
     ValueSource valueSource = new ValueSource() {
       @Override
-      public FunctionValues getValues(@SuppressWarnings("rawtypes") Map context, LeafReaderContext readerContext) throws IOException {
-        final Scorer scorer = (Scorer) context.get("scorer");
+      public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
+        final Scorer scorer = context.getScorer();
         assert scorer != null;
         return new DoubleDocValues(this) {
           @Override
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
index 5c367ac..bf72cd2 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
@@ -17,7 +17,14 @@ package org.apache.lucene.search.grouping;
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.CachingCollector;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.Filter;
@@ -38,13 +45,6 @@ import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.mutable.MutableValue;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
 /**
  * Convenience class to perform grouping in a non distributed environment.
  *
@@ -54,7 +54,7 @@ public class GroupingSearch {
 
   private final String groupField;
   private final ValueSource groupFunction;
-  private final Map<?, ?> valueSourceContext;
+  private final QueryContext valueSourceContext;
   private final Filter groupEndDocs;
 
   private Sort groupSort = Sort.RELEVANCE;
@@ -93,7 +93,7 @@ public class GroupingSearch {
    * @param groupFunction      The function to group by specified as {@link ValueSource}
    * @param valueSourceContext The context of the specified groupFunction
    */
-  public GroupingSearch(ValueSource groupFunction, Map<?, ?> valueSourceContext) {
+  public GroupingSearch(ValueSource groupFunction, QueryContext valueSourceContext) {
     this(null, groupFunction, valueSourceContext, null);
   }
 
@@ -107,7 +107,7 @@ public class GroupingSearch {
     this(null, null, null, groupEndDocs);
   }
 
-  private GroupingSearch(String groupField, ValueSource groupFunction, Map<?, ?> valueSourceContext, Filter groupEndDocs) {
+  private GroupingSearch(String groupField, ValueSource groupFunction, QueryContext valueSourceContext, Filter groupEndDocs) {
     this.groupField = groupField;
     this.groupFunction = groupFunction;
     this.valueSourceContext = valueSourceContext;
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java
index 1c76c85..54ec110 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java
@@ -20,6 +20,7 @@ package org.apache.lucene.search.grouping.function;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.FieldComparator;
 import org.apache.lucene.search.LeafFieldComparator;
 import org.apache.lucene.search.Scorer;
@@ -42,7 +43,7 @@ import java.util.Map;
 public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollector<FunctionAllGroupHeadsCollector.GroupHead> {
 
   private final ValueSource groupBy;
-  private final Map<?, ?> vsContext;
+  private final QueryContext vsContext;
   private final Map<MutableValue, GroupHead> groups;
   private final Sort sortWithinGroup;
 
@@ -55,15 +56,15 @@ public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollect
    * Constructs a {@link FunctionAllGroupHeadsCollector} instance.
    *
    * @param groupBy The {@link ValueSource} to group by
-   * @param vsContext The ValueSource context
+   * @param valueSourceContext The ValueSource context
    * @param sortWithinGroup The sort within a group
    */
-  public FunctionAllGroupHeadsCollector(ValueSource groupBy, Map<?, ?> vsContext, Sort sortWithinGroup) {
+  public FunctionAllGroupHeadsCollector(ValueSource groupBy, QueryContext valueSourceContext, Sort sortWithinGroup) {
     super(sortWithinGroup.getSort().length);
     groups = new HashMap<>();
     this.sortWithinGroup = sortWithinGroup;
     this.groupBy = groupBy;
-    this.vsContext = vsContext;
+    this.vsContext = valueSourceContext;
 
     final SortField[] sortFields = sortWithinGroup.getSort();
     for (int i = 0; i < sortFields.length; i++) {
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java
index c6f1ad9..c593818 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java
@@ -17,18 +17,18 @@ package org.apache.lucene.search.grouping.function;
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.Collection;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.grouping.AbstractAllGroupsCollector;
 import org.apache.lucene.util.mutable.MutableValue;
 
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
 /**
  * A collector that collects all groups that match the
  * query. Only the group value is collected, and the order
@@ -42,7 +42,7 @@ import java.util.TreeSet;
  */
 public class FunctionAllGroupsCollector extends AbstractAllGroupsCollector<MutableValue> {
 
-  private final Map<?, ?> vsContext;
+  private final QueryContext vsContext;
   private final ValueSource groupBy;
   private final SortedSet<MutableValue> groups = new TreeSet<>();
 
@@ -55,7 +55,7 @@ public class FunctionAllGroupsCollector extends AbstractAllGroupsCollector<Mutab
    * @param groupBy The {@link ValueSource} to group by
    * @param vsContext The ValueSource context
    */
-  public FunctionAllGroupsCollector(ValueSource groupBy, Map<?, ?> vsContext) {
+  public FunctionAllGroupsCollector(ValueSource groupBy, QueryContext vsContext) {
     this.vsContext = vsContext;
     this.groupBy = groupBy;
   }
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionDistinctValuesCollector.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionDistinctValuesCollector.java
index 9bcb9b6..d199b14 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionDistinctValuesCollector.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionDistinctValuesCollector.java
@@ -20,6 +20,7 @@ package org.apache.lucene.search.grouping.function;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.grouping.AbstractDistinctValuesCollector;
 import org.apache.lucene.search.grouping.SearchGroup;
 import org.apache.lucene.util.mutable.MutableValue;
@@ -34,7 +35,7 @@ import java.util.*;
  */
 public class FunctionDistinctValuesCollector extends AbstractDistinctValuesCollector<FunctionDistinctValuesCollector.GroupCount> {
 
-  private final Map<?, ?> vsContext;
+  private final QueryContext vsContext;
   private final ValueSource groupSource;
   private final ValueSource countSource;
   private final Map<MutableValue, GroupCount> groupMap;
@@ -44,7 +45,7 @@ public class FunctionDistinctValuesCollector extends AbstractDistinctValuesColle
   private MutableValue groupMval;
   private MutableValue countMval;
 
-  public FunctionDistinctValuesCollector(Map<?, ?> vsContext, ValueSource groupSource, ValueSource countSource, Collection<SearchGroup<MutableValue>> groups) {
+  public FunctionDistinctValuesCollector(QueryContext vsContext, ValueSource groupSource, ValueSource countSource, Collection<SearchGroup<MutableValue>> groups) {
     this.vsContext = vsContext;
     this.groupSource = groupSource;
     this.countSource = countSource;
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java
index 2d3f457..fb60063 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java
@@ -20,6 +20,7 @@ package org.apache.lucene.search.grouping.function;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.grouping.AbstractFirstPassGroupingCollector;
 import org.apache.lucene.util.mutable.MutableValue;
@@ -36,7 +37,7 @@ import java.util.Map;
 public class FunctionFirstPassGroupingCollector extends AbstractFirstPassGroupingCollector<MutableValue> {
 
   private final ValueSource groupByVS;
-  private final Map<?, ?> vsContext;
+  private final QueryContext vsContext;
 
   private FunctionValues.ValueFiller filler;
   private MutableValue mval;
@@ -45,7 +46,7 @@ public class FunctionFirstPassGroupingCollector extends AbstractFirstPassGroupin
    * Creates a first pass collector.
    *
    * @param groupByVS  The {@link ValueSource} instance to group by
-   * @param vsContext  The ValueSource context
+   * @param valueSourceContext  The ValueSource context
    * @param groupSort  The {@link Sort} used to sort the
    *                   groups.  The top sorted document within each group
    *                   according to groupSort, determines how that group
@@ -55,10 +56,10 @@ public class FunctionFirstPassGroupingCollector extends AbstractFirstPassGroupin
    * @param topNGroups How many top groups to keep.
    * @throws IOException When I/O related errors occur
    */
-  public FunctionFirstPassGroupingCollector(ValueSource groupByVS, Map<?, ?> vsContext, Sort groupSort, int topNGroups) throws IOException {
+  public FunctionFirstPassGroupingCollector(ValueSource groupByVS, QueryContext valueSourceContext, Sort groupSort, int topNGroups) throws IOException {
     super(groupSort, topNGroups);
     this.groupByVS = groupByVS;
-    this.vsContext = vsContext;
+    this.vsContext = valueSourceContext;
   }
 
   @Override
diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java
index a58cc80..ca92bc6 100644
--- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java
+++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java
@@ -17,18 +17,18 @@ package org.apache.lucene.search.grouping.function;
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.Collection;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.grouping.AbstractSecondPassGroupingCollector;
 import org.apache.lucene.search.grouping.SearchGroup;
-import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.search.grouping.TopGroups; //javadoc
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Map;
+import org.apache.lucene.util.mutable.MutableValue;
 
 /**
  * Concrete implementation of {@link AbstractSecondPassGroupingCollector} that groups based on
@@ -39,7 +39,7 @@ import java.util.Map;
 public class FunctionSecondPassGroupingCollector extends AbstractSecondPassGroupingCollector<MutableValue> {
 
   private final ValueSource groupByVS;
-  private final Map<?, ?> vsContext;
+  private final QueryContext vsContext;
 
   private FunctionValues.ValueFiller filler;
   private MutableValue mval;
@@ -55,13 +55,13 @@ public class FunctionSecondPassGroupingCollector extends AbstractSecondPassGroup
    * @param getMaxScores Whether to include the maximum score
    * @param fillSortFields Whether to fill the sort values in {@link TopGroups#withinGroupSort}
    * @param groupByVS The {@link ValueSource} to group by
-   * @param vsContext The value source context
+   * @param valueSourceContext The value source context
    * @throws IOException IOException When I/O related errors occur
    */
-  public FunctionSecondPassGroupingCollector(Collection<SearchGroup<MutableValue>> searchGroups, Sort groupSort, Sort withinGroupSort, int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields, ValueSource groupByVS, Map<?, ?> vsContext) throws IOException {
+  public FunctionSecondPassGroupingCollector(Collection<SearchGroup<MutableValue>> searchGroups, Sort groupSort, Sort withinGroupSort, int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields, ValueSource groupByVS, QueryContext valueSourceContext) throws IOException {
     super(searchGroups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
     this.groupByVS = groupByVS;
-    this.vsContext = vsContext;
+    this.vsContext = valueSourceContext;
   }
 
   @Override
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupHeadsCollectorTest.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupHeadsCollectorTest.java
index d5fc31a..67c60bb 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupHeadsCollectorTest.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupHeadsCollectorTest.java
@@ -43,6 +43,7 @@ import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.ScoreDoc;
@@ -508,7 +509,7 @@ public class AllGroupHeadsCollectorTest extends LuceneTestCase {
     AbstractAllGroupHeadsCollector<? extends AbstractAllGroupHeadsCollector.GroupHead> collector;
     if (random().nextBoolean()) {
       ValueSource vs = new BytesRefFieldSource(groupField);
-      collector =  new FunctionAllGroupHeadsCollector(vs, new HashMap<>(), sortWithinGroup);
+      collector =  new FunctionAllGroupHeadsCollector(vs, new QueryContext(), sortWithinGroup);
     } else {
       collector =  TermAllGroupHeadsCollector.create(groupField, sortWithinGroup);
     }
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupsCollectorTest.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupsCollectorTest.java
index 7b72864..f1ae8b9 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupsCollectorTest.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/AllGroupsCollectorTest.java
@@ -27,6 +27,7 @@ import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.grouping.function.FunctionAllGroupsCollector;
@@ -35,8 +36,6 @@ import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;
 
-import java.util.HashMap;
-
 public class AllGroupsCollectorTest extends LuceneTestCase {
 
   public void testTotalGroupCount() throws Exception {
@@ -130,7 +129,7 @@ public class AllGroupsCollectorTest extends LuceneTestCase {
       selected = new TermAllGroupsCollector(groupField);
     } else {
       ValueSource vs = new BytesRefFieldSource(groupField);
-      selected = new FunctionAllGroupsCollector(vs, new HashMap<>());
+      selected = new FunctionAllGroupsCollector(vs, new QueryContext());
     }
 
     if (VERBOSE) {
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/DistinctValuesCollectorTest.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/DistinctValuesCollectorTest.java
index 62c5150..049d35e 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/DistinctValuesCollectorTest.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/DistinctValuesCollectorTest.java
@@ -42,6 +42,7 @@ import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.SortField;
@@ -358,7 +359,7 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
     Random random = random();
     Collection<SearchGroup<T>> searchGroups = firstPassGroupingCollector.getTopGroups(0, false);
     if (FunctionFirstPassGroupingCollector.class.isAssignableFrom(firstPassGroupingCollector.getClass())) {
-      return (AbstractDistinctValuesCollector) new FunctionDistinctValuesCollector(new HashMap<>(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), (Collection) searchGroups);
+      return (AbstractDistinctValuesCollector) new FunctionDistinctValuesCollector(new QueryContext(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), (Collection) searchGroups);
     } else {
       return (AbstractDistinctValuesCollector) new TermDistinctValuesCollector(groupField, countField, (Collection) searchGroups);
     }
@@ -368,7 +369,7 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
   private <T> AbstractFirstPassGroupingCollector<T> createRandomFirstPassCollector(Sort groupSort, String groupField, int topNGroups) throws IOException {
     Random random = random();
     if (random.nextBoolean()) {
-      return (AbstractFirstPassGroupingCollector<T>) new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new HashMap<>(), groupSort, topNGroups);
+      return (AbstractFirstPassGroupingCollector<T>) new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new QueryContext(), groupSort, topNGroups);
     } else {
       return (AbstractFirstPassGroupingCollector<T>) new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups);
     }
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/GroupingSearchTest.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/GroupingSearchTest.java
index cbbfd60..4ba68c9 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/GroupingSearchTest.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/GroupingSearchTest.java
@@ -28,6 +28,7 @@ import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.CachingWrapperFilter;
 import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.IndexSearcher;
@@ -206,7 +207,7 @@ public class GroupingSearchTest extends LuceneTestCase {
     GroupingSearch groupingSearch;
     if (random().nextBoolean()) {
       ValueSource vs = new BytesRefFieldSource(groupField);
-      groupingSearch = new GroupingSearch(vs, new HashMap<>());
+      groupingSearch = new GroupingSearch(vs, new QueryContext());
     } else {
       groupingSearch = new GroupingSearch(groupField);
     }
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
index c01b4ec..a9d97dd 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
@@ -50,6 +50,7 @@ import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.CachingCollector;
 import org.apache.lucene.search.CachingWrapperFilter;
 import org.apache.lucene.search.Collector;
@@ -205,7 +206,7 @@ public class TestGrouping extends LuceneTestCase {
     AbstractFirstPassGroupingCollector<?> selected;
     if (random().nextBoolean()) {
       ValueSource vs = new BytesRefFieldSource(groupField);
-      selected = new FunctionFirstPassGroupingCollector(vs, new HashMap<>(), groupSort, topDocs);
+      selected = new FunctionFirstPassGroupingCollector(vs, new QueryContext(), groupSort, topDocs);
     } else {
       selected = new TermFirstPassGroupingCollector(groupField, groupSort, topDocs);
     }
@@ -218,7 +219,7 @@ public class TestGrouping extends LuceneTestCase {
   private AbstractFirstPassGroupingCollector<?> createFirstPassCollector(String groupField, Sort groupSort, int topDocs, AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector) throws IOException {
     if (TermFirstPassGroupingCollector.class.isAssignableFrom(firstPassGroupingCollector.getClass())) {
       ValueSource vs = new BytesRefFieldSource(groupField);
-      return new FunctionFirstPassGroupingCollector(vs, new HashMap<>(), groupSort, topDocs);
+      return new FunctionFirstPassGroupingCollector(vs, new QueryContext(), groupSort, topDocs);
     } else {
       return new TermFirstPassGroupingCollector(groupField, groupSort, topDocs);
     }
@@ -241,7 +242,7 @@ public class TestGrouping extends LuceneTestCase {
     } else {
       ValueSource vs = new BytesRefFieldSource(groupField);
       Collection<SearchGroup<MutableValue>> searchGroups = firstPassGroupingCollector.getTopGroups(groupOffset, fillSortFields);
-      return (AbstractSecondPassGroupingCollector) new FunctionSecondPassGroupingCollector(searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap());
+      return (AbstractSecondPassGroupingCollector) new FunctionSecondPassGroupingCollector(searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new QueryContext());
     }
   }
 
@@ -274,7 +275,7 @@ public class TestGrouping extends LuceneTestCase {
         mvalSearchGroups.add(sg);
       }
 
-      return new FunctionSecondPassGroupingCollector(mvalSearchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap<>());
+      return new FunctionSecondPassGroupingCollector(mvalSearchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new QueryContext());
     }
   }
 
@@ -284,7 +285,7 @@ public class TestGrouping extends LuceneTestCase {
       return new TermAllGroupsCollector(groupField);
     } else {
       ValueSource vs = new BytesRefFieldSource(groupField);
-      return new FunctionAllGroupsCollector(vs, new HashMap<>());
+      return new FunctionAllGroupsCollector(vs, new QueryContext());
     }
   }
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
index 82c9fce..f961d65 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
@@ -20,12 +20,12 @@ package org.apache.lucene.queries.function;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Map;
 import java.util.Set;
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.ComplexExplanation;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.FilterScorer;
@@ -75,7 +75,7 @@ public class BoostedQuery extends Query {
   private class BoostedWeight extends Weight {
     final IndexSearcher searcher;
     Weight qWeight;
-    Map fcontext;
+    QueryContext fcontext;
 
     public BoostedWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
       super(BoostedQuery.this);
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
index b338452..ecffc20 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
@@ -24,6 +24,7 @@ import java.util.Set;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.ComplexExplanation;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
@@ -69,7 +70,7 @@ public class FunctionQuery extends Query {
     protected final IndexSearcher searcher;
     protected float queryNorm;
     protected float queryWeight;
-    protected final Map context;
+    protected final QueryContext context;
 
     public FunctionWeight(IndexSearcher searcher) throws IOException {
       super(FunctionQuery.this);
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/ValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/ValueSource.java
index 14cdc1d..b084195 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/ValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/ValueSource.java
@@ -18,10 +18,9 @@ package org.apache.lucene.queries.function;
  */
 
 import java.io.IOException;
-import java.util.IdentityHashMap;
-import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.FieldComparator;
 import org.apache.lucene.search.FieldComparatorSource;
 import org.apache.lucene.search.IndexSearcher;
@@ -41,7 +40,7 @@ public abstract class ValueSource {
    * Gets the values for this reader and the context that was previously
    * passed to createWeight()
    */
-  public abstract FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException;
+  public abstract FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException;
 
   @Override
   public abstract boolean equals(Object o);
@@ -65,15 +64,15 @@ public abstract class ValueSource {
    * weight info in the context. The context object will be passed to getValues()
    * where this info can be retrieved.
    */
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
   }
 
   /**
    * Returns a new non-threadsafe context map.
    */
-  public static Map newContext(IndexSearcher searcher) {
-    Map context = new IdentityHashMap();
-    context.put("searcher", searcher);
+  public static QueryContext newContext(IndexSearcher searcher) {
+    QueryContext context = new QueryContext();
+    context.setSearcher(searcher);
     return context;
   }
 
@@ -85,7 +84,7 @@ public abstract class ValueSource {
   /**
    * EXPERIMENTAL: This method is subject to change.
    * <p>
-   * Get the SortField for this ValueSource.  Uses the {@link #getValues(java.util.Map, org.apache.lucene.index.LeafReaderContext)}
+   * Get the SortField for this ValueSource.  Uses the {@link #getValues(QueryContext, org.apache.lucene.index.LeafReaderContext)}
    * to populate the SortField.
    *
    * @param reverse true if this is a reverse sort.
@@ -102,16 +101,16 @@ public abstract class ValueSource {
 
     @Override
     public SortField rewrite(IndexSearcher searcher) throws IOException {
-      Map context = newContext(searcher);
+      QueryContext context = newContext(searcher);
       createWeight(context, searcher);
       return new SortField(getField(), new ValueSourceComparatorSource(context), getReverse());
     }
   }
 
   class ValueSourceComparatorSource extends FieldComparatorSource {
-    private final Map context;
+    private final QueryContext context;
 
-    public ValueSourceComparatorSource(Map context) {
+    public ValueSourceComparatorSource(QueryContext context) {
       this.context = context;
     }
 
@@ -131,10 +130,10 @@ public abstract class ValueSource {
     private final double[] values;
     private FunctionValues docVals;
     private double bottom;
-    private final Map fcontext;
+    private final QueryContext fcontext;
     private double topValue;
 
-    ValueSourceComparator(Map fcontext, int numHits) {
+    ValueSourceComparator(QueryContext fcontext, int numHits) {
       this.fcontext = fcontext;
       values = new double[numHits];
     }
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/BytesRefFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/BytesRefFieldSource.java
index aeda1e1..1c0af2c 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/BytesRefFieldSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/BytesRefFieldSource.java
@@ -42,7 +42,7 @@ public class BytesRefFieldSource extends FieldCacheSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FieldInfo fieldInfo = readerContext.reader().getFieldInfos().fieldInfo(field);
 
     // To be sorted or not to be sorted, that is the question
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ConstValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ConstValueSource.java
index 3836d64..fa3a2a0 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ConstValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ConstValueSource.java
@@ -17,13 +17,12 @@
 
 package org.apache.lucene.queries.function.valuesource;
 
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.FloatDocValues;
 
-import java.io.IOException;
-import java.util.Map;
-
 /**
  * <code>ConstValueSource</code> returns a constant for all documents
  */
@@ -42,7 +41,7 @@ public class ConstValueSource extends ConstNumberSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new FloatDocValues(this) {
       @Override
       public float floatVal(int doc) {
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DefFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DefFunction.java
index c51add4..69dfae6 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DefFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DefFunction.java
@@ -16,15 +16,14 @@ package org.apache.lucene.queries.function.valuesource;
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.List;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.util.BytesRefBuilder;
 
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
 /**
  * {@link ValueSource} implementation which only returns the values from the provided
  * ValueSources which are available for a particular docId.  Consequently, when combined
@@ -43,7 +42,7 @@ public class DefFunction extends MultiFunction {
 
 
   @Override
-  public FunctionValues getValues(Map fcontext, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext fcontext, LeafReaderContext readerContext) throws IOException {
 
 
     return new Values(valsArr(sources, fcontext, readerContext)) {
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DocFreqValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DocFreqValueSource.java
index 8d9b7ce..222b8c9 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DocFreqValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DocFreqValueSource.java
@@ -146,15 +146,15 @@ public class DocFreqValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    IndexSearcher searcher = (IndexSearcher)context.get("searcher");
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
+    IndexSearcher searcher = context.getSearcher();
     int docfreq = searcher.getIndexReader().docFreq(new Term(indexedField, indexedBytes));
     return new ConstIntDocValues(docfreq, this);
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
-    context.put("searcher",searcher);
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
+    context.setSearcher(searcher);
   }
 
   @Override
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleConstValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleConstValueSource.java
index 7ff0e5e..7314c5a 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleConstValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleConstValueSource.java
@@ -17,13 +17,12 @@
 
 package org.apache.lucene.queries.function.valuesource;
 
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 
-import java.io.IOException;
-import java.util.Map;
-
 /**
  * Function that returns a constant double value for every document.
  */
@@ -44,7 +43,7 @@ public class DoubleConstValueSource extends ConstNumberSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new DoubleDocValues(this) {
       @Override
       public float floatVal(int doc) {
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleFieldSource.java
index c04a202..08b8d2f 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleFieldSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DoubleFieldSource.java
@@ -18,11 +18,9 @@
 package org.apache.lucene.queries.function.valuesource;
 
 import java.io.IOException;
-import java.util.Map;
 
-import org.apache.lucene.index.LeafReader;
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
@@ -46,7 +44,7 @@ public class DoubleFieldSource extends FieldCacheSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final NumericDocValues arr = DocValues.getNumeric(readerContext.reader(), field);
     final Bits valid = DocValues.getDocsWithField(readerContext.reader(), field);
     return new DoubleDocValues(this) {
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DualFloatFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DualFloatFunction.java
index 35593fb..f1a08b1 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DualFloatFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/DualFloatFunction.java
@@ -52,7 +52,7 @@ public abstract class DualFloatFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues aVals =  a.getValues(context, readerContext);
     final FunctionValues bVals =  b.getValues(context, readerContext);
     return new FloatDocValues(this) {
@@ -76,7 +76,7 @@ public abstract class DualFloatFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     a.createWeight(context,searcher);
     b.createWeight(context,searcher);
   }
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/EnumFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/EnumFieldSource.java
index 59da29d..68de94c 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/EnumFieldSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/EnumFieldSource.java
@@ -96,7 +96,7 @@ public class EnumFieldSource extends FieldCacheSource {
 
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final NumericDocValues arr = DocValues.getNumeric(readerContext.reader(), field);
     final Bits valid = DocValues.getDocsWithField(readerContext.reader(), field);
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/FloatFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/FloatFieldSource.java
index 8f16661..5e984a2 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/FloatFieldSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/FloatFieldSource.java
@@ -45,7 +45,7 @@ public class FloatFieldSource extends FieldCacheSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final NumericDocValues arr = DocValues.getNumeric(readerContext.reader(), field);
     final Bits valid = DocValues.getDocsWithField(readerContext.reader(), field);
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java
index 2ef59df..8813519 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IDFValueSource.java
@@ -46,8 +46,8 @@ public class IDFValueSource extends DocFreqValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    IndexSearcher searcher = (IndexSearcher)context.get("searcher");
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
+    IndexSearcher searcher = context.getSearcher();
     TFIDFSimilarity sim = asTFIDF(searcher.getSimilarity(), field);
     if (sim == null) {
       throw new UnsupportedOperationException("requires a TFIDFSimilarity (such as DefaultSimilarity)");
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IfFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IfFunction.java
index 756b4f5..5fb7e41 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IfFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IfFunction.java
@@ -44,7 +44,7 @@ public class IfFunction extends BoolFunction {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues ifVals = ifSource.getValues(context, readerContext);
     final FunctionValues trueVals = trueSource.getValues(context, readerContext);
     final FunctionValues falseVals = falseSource.getValues(context, readerContext);
@@ -143,7 +143,7 @@ public class IfFunction extends BoolFunction {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     ifSource.createWeight(context, searcher);
     trueSource.createWeight(context, searcher);
     falseSource.createWeight(context, searcher);
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IntFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IntFieldSource.java
index 6d1414d..44258f8 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IntFieldSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/IntFieldSource.java
@@ -46,7 +46,7 @@ public class IntFieldSource extends FieldCacheSource {
 
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final NumericDocValues arr = DocValues.getNumeric(readerContext.reader(), field);
     final Bits valid = DocValues.getDocsWithField(readerContext.reader(), field);
     
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/JoinDocFreqValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/JoinDocFreqValueSource.java
index 90f671b..5ca7fb7 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/JoinDocFreqValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/JoinDocFreqValueSource.java
@@ -54,7 +54,7 @@ public class JoinDocFreqValueSource extends FieldCacheSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException
   {
     final BinaryDocValues terms = DocValues.getBinary(readerContext.reader(), field);
     final IndexReader top = ReaderUtil.getTopLevelContext(readerContext).reader();
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LinearFloatFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LinearFloatFunction.java
index 3b25ee5..ef80c25 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LinearFloatFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LinearFloatFunction.java
@@ -51,7 +51,7 @@ public class LinearFloatFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals =  source.getValues(context, readerContext);
     return new FloatDocValues(this) {
       @Override
@@ -70,7 +70,7 @@ public class LinearFloatFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     source.createWeight(context, searcher);
   }
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LiteralValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LiteralValueSource.java
index ab3f1d8..9694677 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LiteralValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LiteralValueSource.java
@@ -46,7 +46,7 @@ public class LiteralValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
 
     return new StrDocValues(this) {
       @Override
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LongFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LongFieldSource.java
index d5900d9..bbd5069 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LongFieldSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/LongFieldSource.java
@@ -57,7 +57,7 @@ public class LongFieldSource extends FieldCacheSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final NumericDocValues arr = DocValues.getNumeric(readerContext.reader(), field);
     final Bits valid = DocValues.getDocsWithField(readerContext.reader(), field);
     
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MaxDocValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MaxDocValueSource.java
index ccd7326..85f7ee7 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MaxDocValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MaxDocValueSource.java
@@ -41,13 +41,13 @@ public class MaxDocValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
-    context.put("searcher",searcher);
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
+    context.setSearcher(searcher);
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    IndexSearcher searcher = (IndexSearcher)context.get("searcher");
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
+    IndexSearcher searcher = context.getSearcher();
     return new ConstIntDocValues(searcher.getIndexReader().maxDoc(), this);
   }
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiBoolFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiBoolFunction.java
index 0f7bc2e..f94abc6 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiBoolFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiBoolFunction.java
@@ -43,7 +43,7 @@ public abstract class MultiBoolFunction extends BoolFunction {
   protected abstract boolean func(int doc, FunctionValues[] vals);
 
   @Override
-  public BoolDocValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public BoolDocValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues[] vals =  new FunctionValues[sources.size()];
     int i=0;
     for (ValueSource source : sources) {
@@ -103,7 +103,7 @@ public abstract class MultiBoolFunction extends BoolFunction {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     for (ValueSource source : sources) {
       source.createWeight(context, searcher);
     }
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFloatFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFloatFunction.java
index 5360028..eb1e648 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFloatFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFloatFunction.java
@@ -71,7 +71,7 @@ public abstract class MultiFloatFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues[] valsArr = new FunctionValues[sources.length];
     for (int i=0; i<sources.length; i++) {
       valsArr[i] = sources[i].getValues(context, readerContext);
@@ -93,7 +93,7 @@ public abstract class MultiFloatFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     for (ValueSource source : sources)
       source.createWeight(context, searcher);
   }
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFunction.java
index 053031d..837a13e 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiFunction.java
@@ -88,7 +88,7 @@ public abstract class MultiFunction extends ValueSource {
     return sb.toString();
   }
 
-  public static FunctionValues[] valsArr(List<ValueSource> sources, Map fcontext, LeafReaderContext readerContext) throws IOException {
+  public static FunctionValues[] valsArr(List<ValueSource> sources, QueryContext fcontext, LeafReaderContext readerContext) throws IOException {
     final FunctionValues[] valsArr = new FunctionValues[sources.size()];
     int i=0;
     for (ValueSource source : sources) {
@@ -134,7 +134,7 @@ public abstract class MultiFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     for (ValueSource source : sources)
       source.createWeight(context, searcher);
   }
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java
index 32ea93e..21ef620 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NormValueSource.java
@@ -51,13 +51,13 @@ public class NormValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
-    context.put("searcher",searcher);
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
+    context.setSearcher(searcher);
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    IndexSearcher searcher = (IndexSearcher)context.get("searcher");
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
+    IndexSearcher searcher = context.getSearcher();
     final TFIDFSimilarity similarity = IDFValueSource.asTFIDF(searcher.getSimilarity(), field);
     if (similarity == null) {
       throw new UnsupportedOperationException("requires a TFIDFSimilarity (such as DefaultSimilarity)");
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NumDocsValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NumDocsValueSource.java
index 6f92f1e..4316aeb 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NumDocsValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/NumDocsValueSource.java
@@ -41,7 +41,7 @@ public class NumDocsValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     // Searcher has no numdocs so we must use the reader instead
     return new ConstIntDocValues(ReaderUtil.getTopLevelContext(readerContext).reader().numDocs(), this);
   }
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryContext.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryContext.java
new file mode 100644
index 0000000..dd46c11
--- /dev/null
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryContext.java
@@ -0,0 +1,108 @@
+package org.apache.lucene.queries.function.valuesource;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Scorer;
+
+public class QueryContext {
+  private IndexSearcher searcher;
+  private Scorer scorer;
+  private Map<Object,Object> misc;
+
+  public QueryContext() {
+    this.misc = new IdentityHashMap<>();
+  }
+
+  public QueryContext(QueryContext context) {
+    this.searcher = context.searcher;
+    this.scorer = context.scorer;
+    this.misc = new IdentityHashMap<Object,Object>(misc);
+  }
+
+  public IndexSearcher getSearcher() {
+    return searcher;
+  }
+
+  public void setSearcher(IndexSearcher searcher) {
+    this.searcher = searcher;
+  }
+
+  public Scorer getScorer() {
+    return scorer;
+  }
+
+  public void setScorer(Scorer scorer) {
+    this.scorer = scorer;
+  }
+
+  public Object get(Object key) {
+    return misc.get(key);
+  }
+  
+  public Object put(Object key, Object value) {
+    return misc.put(key, value);
+  }
+
+  /*
+   * (Mostly) Auto-generated hash-code and equals methods follow
+   */
+  
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((misc == null) ? 0 : misc.hashCode());
+    result = prime * result + ((scorer == null) ? 0 : scorer.hashCode());
+    result = prime * result + ((searcher == null) ? 0 : searcher.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (!(obj instanceof QueryContext)) {
+      return false;
+    }
+    QueryContext other = (QueryContext) obj;
+    if (misc == null) {
+      if (other.misc != null) {
+        return false;
+      }
+    } else if (!misc.equals(other.misc)) {
+      return false;
+    }
+    
+    // Intentionally use reference equality because it used to be an IdentityHashMap
+    if (scorer != other.scorer) {
+      return false;
+    }
+    if (searcher != other.searcher) {
+      return false;
+    }
+    return true;
+  }
+}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java
index f3ceae3..219ad7a 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/QueryValueSource.java
@@ -54,7 +54,7 @@ public class QueryValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map fcontext, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext fcontext, LeafReaderContext readerContext) throws IOException {
     return new QueryDocValues(this, readerContext, fcontext);
   }
 
@@ -71,7 +71,7 @@ public class QueryValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     Weight w = searcher.createNormalizedWeight(q, true);
     context.put(this, w);
   }
@@ -83,7 +83,7 @@ class QueryDocValues extends FloatDocValues {
   final Bits acceptDocs;
   final Weight weight;
   final float defVal;
-  final Map fcontext;
+  final QueryContext fcontext;
   final Query q;
 
   Scorer scorer;
@@ -95,28 +95,28 @@ class QueryDocValues extends FloatDocValues {
   int lastDocRequested=Integer.MAX_VALUE;
   
 
-  public QueryDocValues(QueryValueSource vs, LeafReaderContext readerContext, Map fcontext) throws IOException {
+  public QueryDocValues(QueryValueSource vs, LeafReaderContext readerContext, QueryContext fcontext2) throws IOException {
     super(vs);
 
     this.readerContext = readerContext;
     this.acceptDocs = readerContext.reader().getLiveDocs();
     this.defVal = vs.defVal;
     this.q = vs.q;
-    this.fcontext = fcontext;
+    this.fcontext = fcontext2;
 
-    Weight w = fcontext==null ? null : (Weight)fcontext.get(vs);
+    Weight w = fcontext2==null ? null : (Weight)fcontext2.get(vs);
     if (w == null) {
       IndexSearcher weightSearcher;
-      if(fcontext == null) {
+      if(fcontext2 == null) {
         weightSearcher = new IndexSearcher(ReaderUtil.getTopLevelContext(readerContext));
       } else {
-        weightSearcher = (IndexSearcher)fcontext.get("searcher");
+        weightSearcher = fcontext2.getSearcher();
         if (weightSearcher == null) {
           weightSearcher = new IndexSearcher(ReaderUtil.getTopLevelContext(readerContext));
         }
       }
-      vs.createWeight(fcontext, weightSearcher);
-      w = (Weight)fcontext.get(vs);
+      vs.createWeight(fcontext2, weightSearcher);
+      w = (Weight)fcontext2.get(vs);
     }
     weight = w;
   }
@@ -251,4 +251,4 @@ class QueryDocValues extends FloatDocValues {
   public String toString(int doc) {
     return "query(" + q + ",def=" + defVal + ")=" + floatVal(doc);
   }
-}
\ No newline at end of file
+}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/RangeMapFloatFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/RangeMapFloatFunction.java
index 6319655..ff522b6 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/RangeMapFloatFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/RangeMapFloatFunction.java
@@ -59,7 +59,7 @@ public class RangeMapFloatFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals =  source.getValues(context, readerContext);
     final FunctionValues targets = target.getValues(context, readerContext);
     final FunctionValues defaults = (this.defaultVal == null) ? null : defaultVal.getValues(context, readerContext);
@@ -77,7 +77,7 @@ public class RangeMapFloatFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     source.createWeight(context, searcher);
   }
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ReciprocalFloatFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ReciprocalFloatFunction.java
index 0c33bf7..b9e1488 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ReciprocalFloatFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ReciprocalFloatFunction.java
@@ -17,15 +17,14 @@
 
 package org.apache.lucene.queries.function.valuesource;
 
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.FloatDocValues;
 import org.apache.lucene.search.IndexSearcher;
 
-import java.io.IOException;
-import java.util.Map;
-
 /**
  * <code>ReciprocalFloatFunction</code> implements a reciprocal function f(x) = a/(mx+b), based on
  * the float value of a field or function as exported by {@link org.apache.lucene.queries.function.ValueSource}.
@@ -61,7 +60,7 @@ public class ReciprocalFloatFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals = source.getValues(context, readerContext);
     return new FloatDocValues(this) {
       @Override
@@ -82,7 +81,7 @@ public class ReciprocalFloatFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     source.createWeight(context, searcher);
   }
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java
index e346b94..3abca74 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/ScaleFloatFunction.java
@@ -60,7 +60,7 @@ public class ScaleFloatFunction extends ValueSource {
     float maxVal;
   }
 
-  private ScaleInfo createScaleInfo(Map context, LeafReaderContext readerContext) throws IOException {
+  private ScaleInfo createScaleInfo(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final List<LeafReaderContext> leaves = ReaderUtil.getTopLevelContext(readerContext).leaves();
 
     float minVal = Float.POSITIVE_INFINITY;
@@ -101,7 +101,7 @@ public class ScaleFloatFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
 
     ScaleInfo scaleInfo = (ScaleInfo)context.get(ScaleFloatFunction.this);
     if (scaleInfo == null) {
@@ -134,7 +134,7 @@ public class ScaleFloatFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     source.createWeight(context, searcher);
   }
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleBoolFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleBoolFunction.java
index b944b9b..a2b9dfb 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleBoolFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleBoolFunction.java
@@ -17,15 +17,14 @@
 
 package org.apache.lucene.queries.function.valuesource;
 
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.BoolDocValues;
 import org.apache.lucene.search.IndexSearcher;
 
-import java.io.IOException;
-import java.util.Map;
-
 /**
  * {@link BoolFunction} implementation which applies an extendible boolean
  * function to the values of a single wrapped {@link ValueSource}.
@@ -45,7 +44,7 @@ public abstract class SimpleBoolFunction extends BoolFunction {
   protected abstract boolean func(int doc, FunctionValues vals);
 
   @Override
-  public BoolDocValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public BoolDocValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals =  source.getValues(context, readerContext);
     return new BoolDocValues(this) {
       @Override
@@ -77,7 +76,7 @@ public abstract class SimpleBoolFunction extends BoolFunction {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     source.createWeight(context, searcher);
   }
 }
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleFloatFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleFloatFunction.java
index 050b80e..879e067 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleFloatFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleFloatFunction.java
@@ -35,7 +35,7 @@ import java.util.Map;
   protected abstract float func(int doc, FunctionValues vals);
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals =  source.getValues(context, readerContext);
     return new FloatDocValues(this) {
       @Override
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SingleFunction.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SingleFunction.java
index 28e3616..334fb0b 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SingleFunction.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SingleFunction.java
@@ -17,12 +17,11 @@
 
 package org.apache.lucene.queries.function.valuesource;
 
+import java.io.IOException;
+
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.IndexSearcher;
 
-import java.io.IOException;
-import java.util.Map;
-
 /** A function with a single argument
  */
  public abstract class SingleFunction extends ValueSource {
@@ -53,7 +52,7 @@ import java.util.Map;
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     source.createWeight(context, searcher);
   }
 }
\ No newline at end of file
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SortedSetFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SortedSetFieldSource.java
index cbb3085..3d0053e 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SortedSetFieldSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SortedSetFieldSource.java
@@ -49,7 +49,7 @@ public class SortedSetFieldSource extends FieldCacheSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     SortedSetDocValues sortedSet = DocValues.getSortedSet(readerContext.reader(), field);
     SortedDocValues view = SortedSetSelector.wrap(sortedSet, selector);
     return new DocTermsIndexDocValues(this, view) {
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SumTotalTermFreqValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SumTotalTermFreqValueSource.java
index 6b7a7fa..beb7c5a 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SumTotalTermFreqValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SumTotalTermFreqValueSource.java
@@ -52,12 +52,12 @@ public class SumTotalTermFreqValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return (FunctionValues)context.get(this);
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     long sumTotalTermFreq = 0;
     for (LeafReaderContext readerContext : searcher.getTopReaderContext().leaves()) {
       Terms terms = readerContext.reader().terms(indexedField);
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java
index e468df6..2956b52 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TFValueSource.java
@@ -50,10 +50,10 @@ public class TFValueSource extends TermFreqValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     Fields fields = readerContext.reader().fields();
     final Terms terms = fields.terms(indexedField);
-    IndexSearcher searcher = (IndexSearcher)context.get("searcher");
+    IndexSearcher searcher = context.getSearcher();
     final TFIDFSimilarity similarity = IDFValueSource.asTFIDF(searcher.getSimilarity(), indexedField);
     if (similarity == null) {
       throw new UnsupportedOperationException("requires a TFIDFSimilarity (such as DefaultSimilarity)");
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TermFreqValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TermFreqValueSource.java
index b63f4ce..79116bf 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TermFreqValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TermFreqValueSource.java
@@ -48,7 +48,7 @@ public class TermFreqValueSource extends DocFreqValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     Fields fields = readerContext.reader().fields();
     final Terms terms = fields.terms(indexedField);
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TotalTermFreqValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TotalTermFreqValueSource.java
index 5002928..bc6e081 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TotalTermFreqValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/TotalTermFreqValueSource.java
@@ -58,12 +58,12 @@ public class TotalTermFreqValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return (FunctionValues)context.get(this);
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     long totalTermFreq = 0;
     for (LeafReaderContext readerContext : searcher.getTopReaderContext().leaves()) {
       long val = readerContext.reader().totalTermFreq(new Term(indexedField, indexedBytes));
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/VectorValueSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/VectorValueSource.java
index 78db619..5c296be 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/VectorValueSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/VectorValueSource.java
@@ -16,15 +16,14 @@ package org.apache.lucene.queries.function.valuesource;
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.List;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.IndexSearcher;
 
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
 
 /**
  * Converts individual ValueSource instances to leverage the FunctionValues *Val functions that work with multiple values,
@@ -53,7 +52,7 @@ public class VectorValueSource extends MultiValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     int size = sources.size();
 
     // special-case x,y and lat,lon since it's so common
@@ -180,7 +179,7 @@ public class VectorValueSource extends MultiValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     for (ValueSource source : sources)
       source.createWeight(context, searcher);
   }
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java
index c689198..d182f0d 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestSortedSetFieldSource.java
@@ -25,6 +25,7 @@ import org.apache.lucene.document.SortedSetDocValuesField;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.queries.function.valuesource.SortedSetFieldSource;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
@@ -50,7 +51,7 @@ public class TestSortedSetFieldSource extends LuceneTestCase {
     LeafReader ar = getOnlySegmentReader(ir);
     
     ValueSource vs = new SortedSetFieldSource("value");
-    FunctionValues values = vs.getValues(Collections.emptyMap(), ar.getContext());
+    FunctionValues values = vs.getValues(new QueryContext(), ar.getContext());
     assertEquals("baz", values.strVal(0));
     assertEquals("bar", values.strVal(1)); 
     ir.close();
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java
index b66c1e2..120dc23 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java
@@ -17,10 +17,10 @@ package org.apache.lucene.queries.function;
  * limitations under the License.
  */
 
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
-import java.io.IOException;
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
@@ -33,11 +33,11 @@ import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedDocValuesField;
 import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
-import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.docvalues.FloatDocValues;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
 import org.apache.lucene.queries.function.valuesource.ConstValueSource;
@@ -61,6 +61,7 @@ import org.apache.lucene.queries.function.valuesource.NormValueSource;
 import org.apache.lucene.queries.function.valuesource.NumDocsValueSource;
 import org.apache.lucene.queries.function.valuesource.PowFloatFunction;
 import org.apache.lucene.queries.function.valuesource.ProductFloatFunction;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.queries.function.valuesource.QueryValueSource;
 import org.apache.lucene.queries.function.valuesource.RangeMapFloatFunction;
 import org.apache.lucene.queries.function.valuesource.ReciprocalFloatFunction;
@@ -76,8 +77,8 @@ import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.SortField;
-import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.store.Directory;
@@ -543,7 +544,7 @@ public class TestValueSources extends LuceneTestCase {
    * value from the <code>expected</code> {@link ValueSource}
    */
   void assertExists(ValueSource expected, ValueSource actual) {
-    Map context = ValueSource.newContext(searcher);
+    QueryContext context = ValueSource.newContext(searcher);
     try {
       expected.createWeight(context, searcher);
       actual.createWeight(context, searcher);
@@ -607,7 +608,7 @@ public class TestValueSources extends LuceneTestCase {
     }
     
     @Override
-    public FunctionValues getValues(Map context, LeafReaderContext readerContext) {
+    public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) {
       return new FloatDocValues(this) {
         @Override
         public float floatVal(int doc) {
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
index 3a0bbc7..4469c73 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
@@ -17,16 +17,17 @@ package org.apache.lucene.spatial.bbox;
  * limitations under the License.
  */
 
-import com.spatial4j.core.shape.Rectangle;
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.shape.Rectangle;
 
 /**
  * A base class for calculating a spatial relevance rank per document from a provided
@@ -47,7 +48,7 @@ public abstract class BBoxSimilarityValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     bboxValueSource.createWeight(context, searcher);
   }
 
@@ -60,7 +61,7 @@ public abstract class BBoxSimilarityValueSource extends ValueSource {
   protected abstract String similarityDescription();
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
 
     final FunctionValues shapeValues = bboxValueSource.getValues(context, readerContext);
 
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java
index 6c9a929..5c23fad 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java
@@ -17,18 +17,19 @@ package org.apache.lucene.spatial.bbox;
  * limitations under the License.
  */
 
-import com.spatial4j.core.shape.Rectangle;
+import java.io.IOException;
+
+import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.util.Bits;
 
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.shape.Rectangle;
 
 /**
  * A ValueSource in which the indexed Rectangle is returned from
@@ -50,7 +51,7 @@ class BBoxValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     LeafReader reader = readerContext.reader();
     final NumericDocValues minX = DocValues.getNumeric(reader, strategy.field_minX);
     final NumericDocValues minY = DocValues.getNumeric(reader, strategy.field_minY);
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java b/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java
index 4a398d8..2270763 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java
@@ -17,17 +17,20 @@ package org.apache.lucene.spatial.serialized;
  * limitations under the License.
  */
 
-import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.io.BinaryCodec;
-import com.spatial4j.core.shape.Point;
-import com.spatial4j.core.shape.Shape;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
 
 import org.apache.lucene.document.BinaryDocValuesField;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.BinaryDocValues;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Explanation;
@@ -41,13 +44,10 @@ import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.context.SpatialContext;
+import com.spatial4j.core.io.BinaryCodec;
+import com.spatial4j.core.shape.Point;
+import com.spatial4j.core.shape.Shape;
 
 
 /**
@@ -213,7 +213,7 @@ public class SerializedDVStrategy extends SpatialStrategy {
     }
 
     @Override
-    public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+    public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
       final BinaryDocValues docValues = readerContext.reader().getBinaryDocValues(fieldName);
 
       return new FunctionValues() {
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/CachingDoubleValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/CachingDoubleValueSource.java
index 9a91782..8453bb5 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/CachingDoubleValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/CachingDoubleValueSource.java
@@ -17,14 +17,15 @@
 
 package org.apache.lucene.spatial.util;
 
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.queries.function.FunctionValues;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
+
 /**
  * Caches the doubleVal of another value source in a HashMap
  * so that it is computed only once.
@@ -47,7 +48,7 @@ public class CachingDoubleValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final int base = readerContext.docBase;
     final FunctionValues vals = source.getValues(context,readerContext);
     return new FunctionValues() {
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java
index 9216a91..0a70114 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java
@@ -17,19 +17,20 @@ package org.apache.lucene.spatial.util;
  * limitations under the License.
  */
 
-import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.distance.DistanceCalculator;
-import com.spatial4j.core.shape.Point;
-import com.spatial4j.core.shape.Shape;
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.context.SpatialContext;
+import com.spatial4j.core.distance.DistanceCalculator;
+import com.spatial4j.core.shape.Point;
+import com.spatial4j.core.shape.Shape;
 
 /**
  * The distance from a provided Point to a Point retrieved from a ValueSource via
@@ -63,12 +64,12 @@ public class DistanceToShapeValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     shapeValueSource.createWeight(context, searcher);
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues shapeValues = shapeValueSource.getValues(context, readerContext);
 
     return new DoubleDocValues(this) {
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java
index c7b7253..328aa11 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java
@@ -18,17 +18,18 @@ package org.apache.lucene.spatial.util;
  */
 
 import java.io.IOException;
-import java.util.Map;
 
-import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.shape.Shape;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 
+import com.spatial4j.core.context.SpatialContext;
+import com.spatial4j.core.shape.Shape;
+
 /**
  * The area of a Shape retrieved from a ValueSource via
  * {@link org.apache.lucene.queries.function.FunctionValues#objectVal(int)}.
@@ -56,12 +57,12 @@ public class ShapeAreaValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     shapeValueSource.createWeight(context, searcher);
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues shapeValues = shapeValueSource.getValues(context, readerContext);
 
     return new DoubleDocValues(this) {
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeFieldCacheDistanceValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeFieldCacheDistanceValueSource.java
index 198b062..c2c2e1b 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeFieldCacheDistanceValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeFieldCacheDistanceValueSource.java
@@ -20,9 +20,11 @@ package org.apache.lucene.spatial.util;
 import com.spatial4j.core.context.SpatialContext;
 import com.spatial4j.core.distance.DistanceCalculator;
 import com.spatial4j.core.shape.Point;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 
 import java.io.IOException;
 import java.util.List;
@@ -57,7 +59,7 @@ public class ShapeFieldCacheDistanceValueSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, final LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, final LeafReaderContext readerContext) throws IOException {
     return new FunctionValues() {
       private final ShapeFieldCache<Point> cache =
           provider.getCache(readerContext.reader());
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java
index fa01371..6ebd9a0 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java
@@ -17,17 +17,18 @@ package org.apache.lucene.spatial.util;
  * limitations under the License.
  */
 
-import com.spatial4j.core.shape.Shape;
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.BoolDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.spatial.query.SpatialOperation;
 
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.shape.Shape;
 
 /**
  * A boolean ValueSource that compares a shape from a provided ValueSource with a given Shape and sees
@@ -59,12 +60,12 @@ public class ShapePredicateValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     shapeValuesource.createWeight(context, searcher);
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues shapeValues = shapeValuesource.getValues(context, readerContext);
 
     return new BoolDocValues(this) {
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/vector/DistanceValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/vector/DistanceValueSource.java
index 85afeae..80771d8 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/vector/DistanceValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/vector/DistanceValueSource.java
@@ -17,18 +17,19 @@ package org.apache.lucene.spatial.vector;
  * limitations under the License.
  */
 
-import com.spatial4j.core.distance.DistanceCalculator;
-import com.spatial4j.core.shape.Point;
+import java.io.IOException;
+
+import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.Bits;
 
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.distance.DistanceCalculator;
+import com.spatial4j.core.shape.Point;
 
 /**
  * An implementation of the Lucene ValueSource model that returns the distance
@@ -63,7 +64,7 @@ public class DistanceValueSource extends ValueSource {
    * Returns the FunctionValues used by the function query.
    */
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     LeafReader reader = readerContext.reader();
 
     final NumericDocValues ptX = DocValues.getNumeric(reader, strategy.getFieldNameX());
diff --git a/lucene/suggest/src/java/org/apache/lucene/search/suggest/DocumentValueSourceDictionary.java b/lucene/suggest/src/java/org/apache/lucene/search/suggest/DocumentValueSourceDictionary.java
index 9eedbc6..98f00c7 100644
--- a/lucene/suggest/src/java/org/apache/lucene/search/suggest/DocumentValueSourceDictionary.java
+++ b/lucene/suggest/src/java/org/apache/lucene/search/suggest/DocumentValueSourceDictionary.java
@@ -18,15 +18,15 @@ package org.apache.lucene.search.suggest;
  */
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.List;
 
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 
 
 /**
@@ -126,7 +126,7 @@ public class DocumentValueSourceDictionary extends DocumentDictionary {
       }
       starts[leaves.size()] = reader.maxDoc();
       currentWeightValues = (leaves.size() > 0) 
-          ? weightsValueSource.getValues(new HashMap<String, Object>(), leaves.get(currentLeafIndex))
+          ? weightsValueSource.getValues(new QueryContext(), leaves.get(currentLeafIndex))
           : null;
     }
     
@@ -143,7 +143,7 @@ public class DocumentValueSourceDictionary extends DocumentDictionary {
       if (subIndex != currentLeafIndex) {
         currentLeafIndex = subIndex;
         try {
-          currentWeightValues = weightsValueSource.getValues(new HashMap<String, Object>(), leaves.get(currentLeafIndex));
+          currentWeightValues = weightsValueSource.getValues(new QueryContext(), leaves.get(currentLeafIndex));
         } catch (IOException e) {
           throw new RuntimeException();
         }
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
index bdde169..a06fb14 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
@@ -20,11 +20,11 @@ package org.apache.solr.analytics.util.valuesource;
 import java.io.IOException;
 import java.text.ParseException;
 import java.util.Date;
-import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.FloatDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueDate;
 import org.apache.solr.analytics.util.AnalyticsParams;
@@ -55,7 +55,7 @@ public class ConstDateSource extends ConstDoubleSource {
   }
   
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new FloatDocValues(this) {
       @Override
       public float floatVal(int doc) {
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java
index 4feb452..2d51456 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java
@@ -18,13 +18,13 @@
 package org.apache.solr.analytics.util.valuesource;
 
 import java.io.IOException;
-import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.valuesource.ConstNumberSource;
 import org.apache.lucene.queries.function.valuesource.ConstValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.solr.analytics.util.AnalyticsParams;
 
 /**
@@ -48,7 +48,7 @@ public class ConstDoubleSource extends ConstNumberSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new DoubleDocValues(this) {
       @Override
       public double doubleVal(int doc) {
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
index 352c933..9fd4458 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
@@ -27,6 +27,7 @@ import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.LongDocValues;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.NumericUtils;
@@ -58,7 +59,7 @@ public class DateFieldSource extends LongFieldSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final NumericDocValues arr = DocValues.getNumeric(readerContext.reader(), field);
     final Bits valid = DocValues.getDocsWithField(readerContext.reader(), field);
     return new LongDocValues(this) {
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java
index 4bf6e61..005f528 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java
@@ -24,6 +24,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
 
 /**
@@ -48,7 +49,7 @@ public abstract class DualDoubleFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues aVals =  a.getValues(context, readerContext);
     final FunctionValues bVals =  b.getValues(context, readerContext);
     return new DoubleDocValues(this) {
@@ -70,7 +71,7 @@ public abstract class DualDoubleFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     a.createWeight(context,searcher);
     b.createWeight(context,searcher);
   }
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
index a360d0c..406d4fe 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.solr.analytics.util.AnalyticsParams;
 import org.apache.solr.schema.TrieDateField;
@@ -57,7 +58,7 @@ public class FilterFieldSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals =  source.getValues(context, readerContext);
     return new FunctionValues() {
 
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java
index 6a954c1..26db964 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java
@@ -25,6 +25,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.LongDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueDate;
 
@@ -60,7 +61,7 @@ public abstract class MultiDateFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues[] valsArr = new FunctionValues[sources.length];
     for (int i=0; i<sources.length; i++) {
       valsArr[i] = sources[i].getValues(context, readerContext);
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java
index a7e9932..6c32080 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java
@@ -19,12 +19,12 @@ package org.apache.solr.analytics.util.valuesource;
 
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
 
 /**
@@ -59,7 +59,7 @@ public abstract class MultiDoubleFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues[] valsArr = new FunctionValues[sources.length];
     for (int i=0; i<sources.length; i++) {
       valsArr[i] = sources[i].getValues(context, readerContext);
@@ -100,7 +100,7 @@ public abstract class MultiDoubleFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     for (ValueSource source : sources)
       source.createWeight(context, searcher);
   }
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiStringFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiStringFunction.java
index a9f1867..b3f314f 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiStringFunction.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiStringFunction.java
@@ -25,6 +25,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.StrDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueStr;
@@ -61,7 +62,7 @@ public abstract class MultiStringFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues[] valsArr = new FunctionValues[sources.length];
     for (int i=0; i<sources.length; i++) {
       valsArr[i] = sources[i].getValues(context, readerContext);
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java
index e150265..f4ab5ca 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java
@@ -24,6 +24,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 
 /**
  * Abstract {@link ValueSource} implementation which wraps one ValueSource
@@ -45,7 +46,7 @@ public abstract class SingleDoubleFunction extends ValueSource {
   abstract double func(int doc, FunctionValues vals);
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals =  source.getValues(context, readerContext);
     return new DoubleDocValues(this) {
       @Override
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java
index 5607291..e64f40f 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java
@@ -24,6 +24,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.StrDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueStr;
@@ -48,7 +49,7 @@ public abstract class SingleStringFunction extends ValueSource {
   abstract CharSequence func(int doc, FunctionValues vals);
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals =  source.getValues(context, readerContext);
     return new StrDocValues(this) {
       @Override
diff --git a/solr/core/src/java/org/apache/solr/handler/component/FieldFacetStats.java b/solr/core/src/java/org/apache/solr/handler/component/FieldFacetStats.java
index 2887ce2..f65ddf3 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/FieldFacetStats.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/FieldFacetStats.java
@@ -29,6 +29,7 @@ import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.SolrIndexSearcher;
@@ -152,7 +153,7 @@ public class FieldFacetStats {
 
   public void setNextReader(LeafReaderContext ctx) throws IOException {
     this.context = ctx;
-    values = valueSource.getValues(Collections.emptyMap(), ctx);
+    values = valueSource.getValues(new QueryContext(), ctx);
     for (StatsValues stats : facetStatsValues.values()) {
       stats.setNextReader(ctx);
     }
diff --git a/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java b/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
index 693da28..44e020e 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
@@ -23,6 +23,7 @@ import java.util.*;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.EnumFieldValue;
 import org.apache.solr.common.SolrException;
@@ -100,7 +101,7 @@ abstract class AbstractStatsValues<T> implements StatsValues {
    * Context to use when retrieving FunctionValues, will be null until/unless 
    * {@link #setNextReader} is called at least once
    */
-  private Map vsContext;
+  private QueryContext vsContext;
   /** 
    * Values to collect, will be null until/unless {@link #setNextReader} is called 
    * at least once 
diff --git a/solr/core/src/java/org/apache/solr/request/NumericFacets.java b/solr/core/src/java/org/apache/solr/request/NumericFacets.java
index 3b43674..dbd2287 100644
--- a/solr/core/src/java/org/apache/solr/request/NumericFacets.java
+++ b/solr/core/src/java/org/apache/solr/request/NumericFacets.java
@@ -37,6 +37,7 @@ import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.CharsRefBuilder;
@@ -249,7 +250,7 @@ final class NumericFacets {
       // Entries from the PQ first, then using the terms dictionary
       for (Entry entry : counts) {
         final int readerIdx = ReaderUtil.subIndex(entry.docID, leaves);
-        final FunctionValues values = vs.getValues(Collections.emptyMap(), leaves.get(readerIdx));
+        final FunctionValues values = vs.getValues(new QueryContext(), leaves.get(readerIdx));
         result.add(values.strVal(entry.docID - leaves.get(readerIdx).docBase), entry.count);
       }
 
@@ -262,7 +263,7 @@ final class NumericFacets {
         while (pq.size() > 0) {
           Entry entry = pq.pop();
           final int readerIdx = ReaderUtil.subIndex(entry.docID, leaves);
-          final FunctionValues values = vs.getValues(Collections.emptyMap(), leaves.get(readerIdx));
+          final FunctionValues values = vs.getValues(new QueryContext(), leaves.get(readerIdx));
           alreadySeen.add(values.strVal(entry.docID - leaves.get(readerIdx).docBase));
         }
         for (int i = 0; i < result.size(); ++i) {
@@ -318,7 +319,7 @@ final class NumericFacets {
       while (pq.size() > 0) {
         final Entry entry = pq.pop();
         final int readerIdx = ReaderUtil.subIndex(entry.docID, leaves);
-        final FunctionValues values = vs.getValues(Collections.emptyMap(), leaves.get(readerIdx));
+        final FunctionValues values = vs.getValues(new QueryContext(), leaves.get(readerIdx));
         counts.put(values.strVal(entry.docID - leaves.get(readerIdx).docBase), entry.count);
       }
       final Terms terms = searcher.getLeafReader().terms(fieldName);
diff --git a/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java b/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java
index 2db72f9..401373a 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/ValueSourceAugmenter.java
@@ -25,6 +25,7 @@ import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.search.QParser;
@@ -75,7 +76,7 @@ public class ValueSourceAugmenter extends DocTransformer
   }
 
 
-  Map fcontext;
+  QueryContext fcontext;
   SolrIndexSearcher searcher;
   List<LeafReaderContext> readerContexts;
   FunctionValues docValuesArr[];
diff --git a/solr/core/src/java/org/apache/solr/schema/BoolField.java b/solr/core/src/java/org/apache/solr/schema/BoolField.java
index 594507d..2659ae4 100644
--- a/solr/core/src/java/org/apache/solr/schema/BoolField.java
+++ b/solr/core/src/java/org/apache/solr/schema/BoolField.java
@@ -18,18 +18,18 @@
 package org.apache.solr.schema;
 
 import java.io.IOException;
-import java.util.Map;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.Tokenizer;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.BoolDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.uninverting.UninvertingReader.Type;
 import org.apache.lucene.util.BytesRef;
@@ -187,7 +187,7 @@ class BoolFieldSource extends ValueSource {
 
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final SortedDocValues sindex = DocValues.getSorted(readerContext.reader(), field);
 
     // figure out what ord maps to true
diff --git a/solr/core/src/java/org/apache/solr/schema/CurrencyField.java b/solr/core/src/java/org/apache/solr/schema/CurrencyField.java
index 2170607..5927527 100644
--- a/solr/core/src/java/org/apache/solr/schema/CurrencyField.java
+++ b/solr/core/src/java/org/apache/solr/schema/CurrencyField.java
@@ -22,6 +22,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
@@ -388,7 +389,7 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
     }
 
     @Override
-    public FunctionValues getValues(Map context, LeafReaderContext reader) 
+    public FunctionValues getValues(QueryContext context, LeafReaderContext reader) 
       throws IOException {
       final FunctionValues amounts = source.getValues(context, reader);
       // the target digits & currency of our source, 
@@ -501,7 +502,7 @@ public class CurrencyField extends FieldType implements SchemaAware, ResourceLoa
     public Currency getTargetCurrency() { return targetCurrency; }
 
     @Override
-    public FunctionValues getValues(Map context, LeafReaderContext reader) throws IOException {
+    public FunctionValues getValues(QueryContext context, LeafReaderContext reader) throws IOException {
       final FunctionValues amounts = amountValues.getValues(context, reader);
       final FunctionValues currencies = currencyValues.getValues(context, reader);
 
diff --git a/solr/core/src/java/org/apache/solr/schema/LatLonType.java b/solr/core/src/java/org/apache/solr/schema/LatLonType.java
index f9521fb..b274e1e 100644
--- a/solr/core/src/java/org/apache/solr/schema/LatLonType.java
+++ b/solr/core/src/java/org/apache/solr/schema/LatLonType.java
@@ -26,12 +26,14 @@ import com.spatial4j.core.context.SpatialContext;
 import com.spatial4j.core.distance.DistanceUtils;
 import com.spatial4j.core.shape.Point;
 import com.spatial4j.core.shape.Rectangle;
+
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.queries.function.valuesource.VectorValueSource;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
@@ -315,8 +317,8 @@ class SpatialDistanceQuery extends ExtendedQueryBase implements PostFilter {
     protected IndexSearcher searcher;
     protected float queryNorm;
     protected float queryWeight;
-    protected Map latContext;
-    protected Map lonContext;
+    protected QueryContext latContext;
+    protected QueryContext lonContext;
 
     public SpatialWeight(IndexSearcher searcher) throws IOException {
       super(SpatialDistanceQuery.this);
diff --git a/solr/core/src/java/org/apache/solr/schema/RandomSortField.java b/solr/core/src/java/org/apache/solr/schema/RandomSortField.java
index 84dec6f..6fc0153 100644
--- a/solr/core/src/java/org/apache/solr/schema/RandomSortField.java
+++ b/solr/core/src/java/org/apache/solr/schema/RandomSortField.java
@@ -27,6 +27,7 @@ import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.IntDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.*;
 import org.apache.lucene.uninverting.UninvertingReader.Type;
 import org.apache.solr.response.TextResponseWriter;
@@ -174,7 +175,7 @@ public class RandomSortField extends FieldType {
     }
 
     @Override
-    public FunctionValues getValues(Map context, final LeafReaderContext readerContext) throws IOException {
+    public FunctionValues getValues(QueryContext context, final LeafReaderContext readerContext) throws IOException {
       return new IntDocValues(this) {
           private final int seed = getSeed(field, readerContext);
           @Override
diff --git a/solr/core/src/java/org/apache/solr/schema/StrFieldSource.java b/solr/core/src/java/org/apache/solr/schema/StrFieldSource.java
index 9310ed1..830351a 100644
--- a/solr/core/src/java/org/apache/solr/schema/StrFieldSource.java
+++ b/solr/core/src/java/org/apache/solr/schema/StrFieldSource.java
@@ -21,6 +21,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.DocTermsIndexDocValues;
 import org.apache.lucene.queries.function.valuesource.FieldCacheSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 
 import java.io.IOException;
 import java.util.Map;
@@ -37,7 +38,7 @@ public class StrFieldSource extends FieldCacheSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new DocTermsIndexDocValues(this, readerContext, field) {
 
       @Override
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 c560308..7a3e576 100644
--- a/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/CollapsingQParserPlugin.java
@@ -31,6 +31,7 @@ import com.carrotsearch.hppc.IntIntOpenHashMap;
 import com.carrotsearch.hppc.IntLongOpenHashMap;
 import com.carrotsearch.hppc.cursors.IntIntCursor;
 import com.carrotsearch.hppc.cursors.IntLongCursor;
+
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.DocValuesType;
 import org.apache.lucene.index.FieldInfo;
@@ -44,6 +45,7 @@ import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.queries.function.FunctionQuery;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -1632,7 +1634,7 @@ public class CollapsingQParserPlugin extends QParserPlugin {
     private ValueSource valueSource;
     private FunctionValues functionValues;
     private float[] ordVals;
-    private Map rcontext;
+    private QueryContext rcontext;
     private CollapseScore collapseScore = new CollapseScore();
     private float score;
     private boolean cscore;
@@ -1665,7 +1667,7 @@ public class CollapsingQParserPlugin extends QParserPlugin {
 
       if(funcStr.indexOf("cscore()") != -1) {
         this.cscore = true;
-        this.rcontext.put("CSCORE",this.collapseScore);
+        this.rcontext.put("CSCORE", this.collapseScore);
       }
 
       if(this.needsScores) {
@@ -2060,7 +2062,7 @@ public class CollapsingQParserPlugin extends QParserPlugin {
 
     private ValueSource valueSource;
     private FunctionValues functionValues;
-    private Map rcontext;
+    private QueryContext rcontext;
     private CollapseScore collapseScore = new CollapseScore();
     private boolean cscore;
     private float score;
@@ -2096,7 +2098,7 @@ public class CollapsingQParserPlugin extends QParserPlugin {
 
       if(funcStr.indexOf("cscore()") != -1) {
         this.cscore = true;
-        this.rcontext.put("CSCORE",this.collapseScore);
+        this.rcontext.put("CSCORE", this.collapseScore);
       }
 
       if(needsScores) {
diff --git a/solr/core/src/java/org/apache/solr/search/FunctionRangeQuery.java b/solr/core/src/java/org/apache/solr/search/FunctionRangeQuery.java
index 8451f0a..ee04522 100644
--- a/solr/core/src/java/org/apache/solr/search/FunctionRangeQuery.java
+++ b/solr/core/src/java/org/apache/solr/search/FunctionRangeQuery.java
@@ -21,6 +21,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.ValueSourceScorer;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.solr.search.function.ValueSourceRangeFilter;
 
@@ -38,17 +39,17 @@ public class FunctionRangeQuery extends SolrConstantScoreQuery implements PostFi
 
   @Override
   public DelegatingCollector getFilterCollector(IndexSearcher searcher) {
-    Map fcontext = ValueSource.newContext(searcher);
+    QueryContext fcontext = ValueSource.newContext(searcher);
     return new FunctionRangeCollector(fcontext);
   }
 
   class FunctionRangeCollector extends DelegatingCollector {
-    final Map fcontext;
+    final QueryContext fcontext;
     ValueSourceScorer scorer;
     int maxdoc;
 
-    public FunctionRangeCollector(Map fcontext) {
-      this.fcontext = fcontext;
+    public FunctionRangeCollector(QueryContext fcontext2) {
+      this.fcontext = fcontext2;
     }
 
     @Override
diff --git a/solr/core/src/java/org/apache/solr/search/Grouping.java b/solr/core/src/java/org/apache/solr/search/Grouping.java
index 3d478a5..bd6ca26 100644
--- a/solr/core/src/java/org/apache/solr/search/Grouping.java
+++ b/solr/core/src/java/org/apache/solr/search/Grouping.java
@@ -23,7 +23,6 @@ import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.lang.ArrayUtils;
@@ -31,6 +30,7 @@ import org.apache.lucene.index.ExitableDirectoryReader;
 import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionQuery;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.queries.function.valuesource.QueryValueSource;
 import org.apache.lucene.search.CachingCollector;
 import org.apache.lucene.search.Collector;
@@ -913,7 +913,7 @@ public class Grouping {
   public class CommandFunc extends Command<MutableValue> {
 
     public ValueSource groupBy;
-    Map context;
+    QueryContext context;
 
     FunctionFirstPassGroupingCollector firstPass;
     FunctionSecondPassGroupingCollector secondPass;
diff --git a/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java b/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java
index 0051d66..cbcc434 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java
@@ -7,6 +7,7 @@ import java.util.Set;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.ComplexExplanation;
 import org.apache.lucene.search.ConstantScoreQuery;
 import org.apache.lucene.search.DocIdSet;
@@ -104,7 +105,7 @@ public class SolrConstantScoreQuery extends ConstantScoreQuery implements Extend
   protected class ConstantWeight extends Weight {
     private float queryNorm;
     private float queryWeight;
-    private Map context;
+    private QueryContext context;
 
     public ConstantWeight(IndexSearcher searcher) throws IOException {
       super(SolrConstantScoreQuery.this);
diff --git a/solr/core/src/java/org/apache/solr/search/SolrFilter.java b/solr/core/src/java/org/apache/solr/search/SolrFilter.java
index 2383501..4ece86a 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrFilter.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrFilter.java
@@ -17,15 +17,15 @@
 
 package org.apache.solr.search;
 
+import java.io.IOException;
+
 import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
+import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.util.Bits;
 
-import java.util.Map;
-import java.io.IOException;
-
 
 /** A SolrFilter extends the Lucene Filter and adds extra semantics such as passing on
  * weight context info for function queries.
@@ -36,9 +36,9 @@ public abstract class SolrFilter extends Filter {
 
   /** Implementations should propagate createWeight to sub-ValueSources which can store weight info in the context.
    * The context object will be passed to getDocIdSet() where this info can be retrieved. */
-  public abstract void createWeight(Map context, IndexSearcher searcher) throws IOException;
+  public abstract void createWeight(QueryContext context, IndexSearcher searcher) throws IOException;
   
-  public abstract DocIdSet getDocIdSet(Map context, LeafReaderContext readerContext, Bits acceptDocs) throws IOException;
+  public abstract DocIdSet getDocIdSet(QueryContext context, LeafReaderContext readerContext, Bits acceptDocs) throws IOException;
 
   @Override
   public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptDocs) throws IOException {
diff --git a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
index 30a157d..2ab19de 100644
--- a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
@@ -997,7 +997,7 @@ class LongConstValueSource extends ConstNumberSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new LongDocValues(this) {
       @Override
       public float floatVal(int doc) {
@@ -1104,7 +1104,7 @@ abstract class DoubleParser extends NamedParser {
     }
 
     @Override
-    public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+    public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
       final FunctionValues vals =  source.getValues(context, readerContext);
       return new DoubleDocValues(this) {
         @Override
@@ -1152,7 +1152,7 @@ abstract class Double2Parser extends NamedParser {
     }
 
     @Override
-    public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+    public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
       final FunctionValues aVals =  a.getValues(context, readerContext);
       final FunctionValues bVals =  b.getValues(context, readerContext);
       return new DoubleDocValues(this) {
@@ -1168,7 +1168,7 @@ abstract class Double2Parser extends NamedParser {
     }
 
     @Override
-    public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+    public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     }
 
     @Override
@@ -1206,7 +1206,7 @@ class BoolConstValueSource extends ConstNumberSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new BoolDocValues(this) {
       @Override
       public boolean boolVal(int doc) {
@@ -1267,7 +1267,7 @@ class TestValueSource extends ValueSource {
   }
   
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     if (context.get(this) == null) {
       SolrRequestInfo requestInfo = SolrRequestInfo.getRequestInfo();
       throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "testfunc: unweighted value source detected.  delegate="+source + " request=" + (requestInfo==null ? "null" : requestInfo.getReq()));
@@ -1291,7 +1291,7 @@ class TestValueSource extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     context.put(this, this);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/search/function/CollapseScoreFunction.java b/solr/core/src/java/org/apache/solr/search/function/CollapseScoreFunction.java
index 4034c4d..d2b0a70 100644
--- a/solr/core/src/java/org/apache/solr/search/function/CollapseScoreFunction.java
+++ b/solr/core/src/java/org/apache/solr/search/function/CollapseScoreFunction.java
@@ -20,7 +20,9 @@ package org.apache.solr.search.function;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.FunctionValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.solr.search.CollapsingQParserPlugin.CollapseScore;
+
 import java.util.Map;
 import java.io.IOException;
 
@@ -42,7 +44,7 @@ public class CollapseScoreFunction extends ValueSource {
     return 1213241257;
   }
 
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     return new CollapseScoreFunctionValues(context);
   }
 
@@ -50,7 +52,7 @@ public class CollapseScoreFunction extends ValueSource {
 
     private CollapseScore cscore;
 
-    public CollapseScoreFunctionValues(Map context) {
+    public CollapseScoreFunctionValues(QueryContext context) {
       this.cscore = (CollapseScore) context.get("CSCORE");
     }
 
diff --git a/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java b/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java
index 1817281..bca9062 100644
--- a/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java
+++ b/solr/core/src/java/org/apache/solr/search/function/FileFloatSource.java
@@ -20,6 +20,7 @@ import org.apache.lucene.index.*;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.FloatDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.solr.core.SolrCore;
@@ -77,7 +78,7 @@ public class FileFloatSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final int off = readerContext.docBase;
     IndexReaderContext topLevelContext = ReaderUtil.getTopLevelContext(readerContext);
 
diff --git a/solr/core/src/java/org/apache/solr/search/function/OrdFieldSource.java b/solr/core/src/java/org/apache/solr/search/function/OrdFieldSource.java
index 194bec5..73c33b8 100644
--- a/solr/core/src/java/org/apache/solr/search/function/OrdFieldSource.java
+++ b/solr/core/src/java/org/apache/solr/search/function/OrdFieldSource.java
@@ -32,6 +32,8 @@ import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.IntDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.SortedSetSelector;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueInt;
@@ -71,10 +73,10 @@ public class OrdFieldSource extends ValueSource {
 
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final int off = readerContext.docBase;
     final LeafReader r;
-    Object o = context.get("searcher");
+    IndexSearcher o = context.getSearcher();
     if (o instanceof SolrIndexSearcher) {
       SolrIndexSearcher is = (SolrIndexSearcher) o;
       SchemaField sf = is.getSchema().getFieldOrNull(field);
diff --git a/solr/core/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java b/solr/core/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java
index a37748f..4077cb7 100644
--- a/solr/core/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java
+++ b/solr/core/src/java/org/apache/solr/search/function/ReverseOrdFieldSource.java
@@ -32,6 +32,8 @@ import org.apache.lucene.index.SortedDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.IntDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.SortedSetSelector;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.Insanity;
@@ -71,10 +73,10 @@ public class ReverseOrdFieldSource extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final int off = readerContext.docBase;
     final LeafReader r;
-    Object o = context.get("searcher");
+    IndexSearcher o = context.getSearcher();
     if (o instanceof SolrIndexSearcher) {
       SolrIndexSearcher is = (SolrIndexSearcher) o;
       SchemaField sf = is.getSchema().getFieldOrNull(field);
diff --git a/solr/core/src/java/org/apache/solr/search/function/ValueSourceRangeFilter.java b/solr/core/src/java/org/apache/solr/search/function/ValueSourceRangeFilter.java
index 39d2e4e..0027fef 100644
--- a/solr/core/src/java/org/apache/solr/search/function/ValueSourceRangeFilter.java
+++ b/solr/core/src/java/org/apache/solr/search/function/ValueSourceRangeFilter.java
@@ -19,6 +19,7 @@ package org.apache.solr.search.function;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.IndexSearcher;
@@ -74,7 +75,7 @@ public class ValueSourceRangeFilter extends SolrFilter {
 
 
   @Override
-  public DocIdSet getDocIdSet(final Map context, final LeafReaderContext readerContext, Bits acceptDocs) throws IOException {
+  public DocIdSet getDocIdSet(final QueryContext context, final LeafReaderContext readerContext, Bits acceptDocs) throws IOException {
      return BitsFilteredDocIdSet.wrap(new DocIdSet() {
        @Override
        public DocIdSetIterator iterator() throws IOException {
@@ -93,7 +94,7 @@ public class ValueSourceRangeFilter extends SolrFilter {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     valueSource.createWeight(context, searcher);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/search/function/distance/GeohashFunction.java b/solr/core/src/java/org/apache/solr/search/function/distance/GeohashFunction.java
index ae9e091..0f14b53 100644
--- a/solr/core/src/java/org/apache/solr/search/function/distance/GeohashFunction.java
+++ b/solr/core/src/java/org/apache/solr/search/function/distance/GeohashFunction.java
@@ -19,6 +19,8 @@ package org.apache.solr.search.function.distance;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
+
 import com.spatial4j.core.io.GeohashUtils;
 
 import java.util.Map;
@@ -46,7 +48,7 @@ public class GeohashFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues latDV = lat.getValues(context, readerContext);
     final FunctionValues lonDV = lon.getValues(context, readerContext);
 
diff --git a/solr/core/src/java/org/apache/solr/search/function/distance/GeohashHaversineFunction.java b/solr/core/src/java/org/apache/solr/search/function/distance/GeohashHaversineFunction.java
index ec6d367..70b70e3 100644
--- a/solr/core/src/java/org/apache/solr/search/function/distance/GeohashHaversineFunction.java
+++ b/solr/core/src/java/org/apache/solr/search/function/distance/GeohashHaversineFunction.java
@@ -22,10 +22,12 @@ import com.spatial4j.core.distance.DistanceUtils;
 import com.spatial4j.core.distance.GeodesicSphereDistCalc;
 import com.spatial4j.core.io.GeohashUtils;
 import com.spatial4j.core.shape.Point;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
 
 import java.io.IOException;
@@ -61,7 +63,7 @@ public class GeohashHaversineFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues gh1DV = geoHash1.getValues(context, readerContext);
     final FunctionValues gh2DV = geoHash2.getValues(context, readerContext);
 
@@ -98,7 +100,7 @@ public class GeohashHaversineFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     geoHash1.createWeight(context, searcher);
     geoHash2.createWeight(context, searcher);
   }
diff --git a/solr/core/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java b/solr/core/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java
index 03f98f3..5a46b6c 100644
--- a/solr/core/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java
+++ b/solr/core/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java
@@ -17,10 +17,12 @@ package org.apache.solr.search.function.distance;
  */
 
 import com.spatial4j.core.distance.DistanceUtils;
+
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.queries.function.valuesource.VectorValueSource;
 import org.apache.lucene.search.IndexSearcher;
 
@@ -57,7 +59,7 @@ public class HaversineConstFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues latVals = latSource.getValues(context, readerContext);
     final FunctionValues lonVals = lonSource.getValues(context, readerContext);
     final double latCenterRad = this.latCenter * DEGREES_TO_RADIANS;
@@ -85,7 +87,7 @@ public class HaversineConstFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     latSource.createWeight(context, searcher);
     lonSource.createWeight(context, searcher);
   }
diff --git a/solr/core/src/java/org/apache/solr/search/function/distance/HaversineFunction.java b/solr/core/src/java/org/apache/solr/search/function/distance/HaversineFunction.java
index b561f89..26f8f96 100644
--- a/solr/core/src/java/org/apache/solr/search/function/distance/HaversineFunction.java
+++ b/solr/core/src/java/org/apache/solr/search/function/distance/HaversineFunction.java
@@ -21,8 +21,11 @@ import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.valuesource.MultiValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
+
 import com.spatial4j.core.distance.DistanceUtils;
+
 import org.apache.solr.common.SolrException;
 
 import java.io.IOException;
@@ -94,7 +97,7 @@ public class HaversineFunction extends ValueSource {
 
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues vals1 = p1.getValues(context, readerContext);
 
     final FunctionValues vals2 = p2.getValues(context, readerContext);
@@ -115,7 +118,7 @@ public class HaversineFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     p1.createWeight(context, searcher);
     p2.createWeight(context, searcher);
 
diff --git a/solr/core/src/java/org/apache/solr/search/function/distance/StringDistanceFunction.java b/solr/core/src/java/org/apache/solr/search/function/distance/StringDistanceFunction.java
index 5398d8f..81a5e53 100644
--- a/solr/core/src/java/org/apache/solr/search/function/distance/StringDistanceFunction.java
+++ b/solr/core/src/java/org/apache/solr/search/function/distance/StringDistanceFunction.java
@@ -21,6 +21,7 @@ import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.FloatDocValues;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.spell.StringDistance;
 
 import java.io.IOException;
@@ -44,7 +45,7 @@ public class StringDistanceFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
     final FunctionValues str1DV = str1.getValues(context, readerContext);
     final FunctionValues str2DV = str2.getValues(context, readerContext);
     return new FloatDocValues(this) {
diff --git a/solr/core/src/java/org/apache/solr/search/function/distance/VectorDistanceFunction.java b/solr/core/src/java/org/apache/solr/search/function/distance/VectorDistanceFunction.java
index 146203e..2cfca4c 100644
--- a/solr/core/src/java/org/apache/solr/search/function/distance/VectorDistanceFunction.java
+++ b/solr/core/src/java/org/apache/solr/search/function/distance/VectorDistanceFunction.java
@@ -21,6 +21,7 @@ import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.valuesource.MultiValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.solr.common.SolrException;
 
@@ -150,7 +151,7 @@ public class VectorDistanceFunction extends ValueSource {
   }
 
   @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+  public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
 
     final FunctionValues vals1 = source1.getValues(context, readerContext);
 
@@ -178,7 +179,7 @@ public class VectorDistanceFunction extends ValueSource {
   }
 
   @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
+  public void createWeight(QueryContext context, IndexSearcher searcher) throws IOException {
     source1.createWeight(context, searcher);
     source2.createWeight(context, searcher);
   }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java b/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
index 8bc96d3..d776ac9 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/CommandHandler.java
@@ -19,11 +19,11 @@ package org.apache.solr.search.grouping;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 import org.apache.lucene.index.ExitableDirectoryReader;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.MultiCollector;
@@ -32,7 +32,6 @@ import org.apache.lucene.search.TimeLimitingCollector;
 import org.apache.lucene.search.TotalHitCountCollector;
 import org.apache.lucene.search.grouping.AbstractAllGroupHeadsCollector;
 import org.apache.lucene.search.grouping.function.FunctionAllGroupHeadsCollector;
-import org.apache.lucene.search.grouping.function.FunctionAllGroupsCollector;
 import org.apache.lucene.search.grouping.term.TermAllGroupHeadsCollector;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.schema.FieldType;
@@ -171,7 +170,7 @@ public class CommandHandler {
     final AbstractAllGroupHeadsCollector allGroupHeadsCollector;
     if (fieldType.getNumericType() != null) {
       ValueSource vs = fieldType.getValueSource(sf, null);
-      allGroupHeadsCollector = new FunctionAllGroupHeadsCollector(vs, new HashMap<Object,Object>(), firstCommand.getSortWithinGroup());
+      allGroupHeadsCollector = new FunctionAllGroupHeadsCollector(vs, new QueryContext(), firstCommand.getSortWithinGroup());
     } else {
       allGroupHeadsCollector = TermAllGroupHeadsCollector.create(firstCommand.getKey(), firstCommand.getSortWithinGroup());
     }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
index c153e74..6a65342 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/SearchGroupsFieldCommand.java
@@ -18,6 +18,7 @@ package org.apache.solr.search.grouping.distributed.command;
  */
 
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.grouping.AbstractAllGroupsCollector;
@@ -99,7 +100,7 @@ public class SearchGroupsFieldCommand implements Command<Pair<Integer, Collectio
     if (topNGroups > 0) {
       if (fieldType.getNumericType() != null) {
         ValueSource vs = fieldType.getValueSource(field, null);
-        firstPassGroupingCollector = new FunctionFirstPassGroupingCollector(vs, new HashMap<Object,Object>(), groupSort, topNGroups);
+        firstPassGroupingCollector = new FunctionFirstPassGroupingCollector(vs, new QueryContext(), groupSort, topNGroups);
       } else {
         firstPassGroupingCollector = new TermFirstPassGroupingCollector(field.getName(), groupSort, topNGroups);
       }
@@ -108,7 +109,7 @@ public class SearchGroupsFieldCommand implements Command<Pair<Integer, Collectio
     if (includeGroupCount) {
       if (fieldType.getNumericType() != null) {
         ValueSource vs = fieldType.getValueSource(field, null);
-        allGroupsCollector = new FunctionAllGroupsCollector(vs, new HashMap<Object,Object>());
+        allGroupsCollector = new FunctionAllGroupsCollector(vs, new QueryContext());
       } else {
         allGroupsCollector = new TermAllGroupsCollector(field.getName());
       }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java
index eb8b485..2c51cae 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/command/TopGroupsFieldCommand.java
@@ -18,6 +18,7 @@ package org.apache.solr.search.grouping.distributed.command;
  */
 
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.grouping.AbstractSecondPassGroupingCollector;
@@ -137,7 +138,7 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
       ValueSource vs = fieldType.getValueSource(field, null);
       Collection<SearchGroup<MutableValue>> v = GroupConverter.toMutable(field, firstPhaseGroups);
       secondPassCollector = new FunctionSecondPassGroupingCollector(
-          v, groupSort, sortWithinGroup, maxDocPerGroup, needScores, needMaxScore, true, vs, new HashMap<Object,Object>()
+          v, groupSort, sortWithinGroup, maxDocPerGroup, needScores, needMaxScore, true, vs, new QueryContext()
       );
     } else {
       secondPassCollector = new TermSecondPassGroupingCollector(
diff --git a/solr/core/src/java/org/apache/solr/update/VersionInfo.java b/solr/core/src/java/org/apache/solr/update/VersionInfo.java
index c541ac6..f147fed 100644
--- a/solr/core/src/java/org/apache/solr/update/VersionInfo.java
+++ b/solr/core/src/java/org/apache/solr/update/VersionInfo.java
@@ -24,6 +24,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.BitUtil;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.SolrException;
@@ -194,7 +195,7 @@ public class VersionInfo {
       if (lookup < 0) return null;
 
       ValueSource vs = versionField.getType().getValueSource(versionField, null);
-      Map context = ValueSource.newContext(searcher);
+      QueryContext context = ValueSource.newContext(searcher);
       vs.createWeight(context, searcher);
       FunctionValues fv = vs.getValues(context, searcher.getTopReaderContext().leaves().get((int)(lookup>>32)));
       long ver = fv.longVal((int)lookup);
diff --git a/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessorFactory.java
index fcade66..a3df008 100755
--- a/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessorFactory.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/DocBasedVersionConstraintsProcessorFactory.java
@@ -19,6 +19,7 @@ package org.apache.solr.update.processor;
 
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.solr.common.SolrException;
@@ -277,7 +278,7 @@ public class DocBasedVersionConstraintsProcessorFactory extends UpdateRequestPro
             }
 
             ValueSource vs = solrVersionField.getType().getValueSource(solrVersionField, null);
-            Map context = ValueSource.newContext(searcher);
+            QueryContext context = ValueSource.newContext(searcher);
             vs.createWeight(context, searcher);
             FunctionValues fv = vs.getValues(context, searcher.getTopReaderContext().leaves().get((int)(lookup>>32)));
             oldSolrVersion = fv.longVal((int)lookup);
diff --git a/solr/core/src/test/org/apache/solr/core/CountUsageValueSourceParser.java b/solr/core/src/test/org/apache/solr/core/CountUsageValueSourceParser.java
index 2e8132a..4861a21 100644
--- a/solr/core/src/test/org/apache/solr/core/CountUsageValueSourceParser.java
+++ b/solr/core/src/test/org/apache/solr/core/CountUsageValueSourceParser.java
@@ -21,6 +21,7 @@ import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.valuesource.DoubleConstValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.solr.search.FunctionQParser;
 import org.apache.solr.search.SyntaxError;
 import org.apache.solr.search.ValueSourceParser;
@@ -73,7 +74,7 @@ public class CountUsageValueSourceParser extends ValueSourceParser {
       this.counter = counter;
     }
     @Override
-    public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
+    public FunctionValues getValues(QueryContext context, LeafReaderContext readerContext) throws IOException {
       return new DoubleDocValues(this) {
         @Override
         public double doubleVal(int doc) {
diff --git a/solr/core/src/test/org/apache/solr/search/TestIndexSearcher.java b/solr/core/src/test/org/apache/solr/search/TestIndexSearcher.java
index 5eb2bd7..f0f61a7 100644
--- a/solr/core/src/test/org/apache/solr/search/TestIndexSearcher.java
+++ b/solr/core/src/test/org/apache/solr/search/TestIndexSearcher.java
@@ -32,6 +32,7 @@ import org.apache.lucene.index.LogDocMergePolicy;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.QueryContext;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.NamedList;
@@ -76,7 +77,7 @@ public class TestIndexSearcher extends SolrTestCaseJ4 {
   private String getStringVal(SolrQueryRequest sqr, String field, int doc) throws IOException {
     SchemaField sf = sqr.getSchema().getField(field);
     ValueSource vs = sf.getType().getValueSource(sf, null);
-    Map context = ValueSource.newContext(sqr.getSearcher());
+    QueryContext context = ValueSource.newContext(sqr.getSearcher());
     vs.createWeight(context, sqr.getSearcher());
     IndexReaderContext topReaderContext = sqr.getSearcher().getTopReaderContext();
     List<LeafReaderContext> leaves = topReaderContext.leaves();
-- 
1.9.1

