This is an automated email from the ASF dual-hosted git repository.

saurabhd336 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 57f50d3dec Json extract index filter support (#12683)
57f50d3dec is described below

commit 57f50d3dec2a2023effa67ca044f61dfd6561dad
Author: Saurabh Dubey <[email protected]>
AuthorDate: Tue Mar 26 09:22:29 2024 +0530

    Json extract index filter support (#12683)
    
    
    ---------
    
    Co-authored-by: Saurabh Dubey <[email protected]>
    Co-authored-by: Saurabh Dubey 
<[email protected]>
---
 .../common/function/TransformFunctionType.java     |  3 +-
 .../JsonExtractIndexTransformFunction.java         | 28 ++++++----
 .../JsonExtractIndexTransformFunctionTest.java     | 17 +++++++
 .../realtime/impl/json/MutableJsonIndexImpl.java   | 28 +++++++++-
 .../readers/json/ImmutableJsonIndexReader.java     | 46 +++++++++++++++--
 .../segment/local/segment/index/JsonIndexTest.java | 59 ++++++++++++++--------
 .../segment/spi/index/reader/JsonIndexReader.java  |  3 +-
 7 files changed, 147 insertions(+), 37 deletions(-)

diff --git 
a/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
 
b/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
index 20bc26854c..88c269c6aa 100644
--- 
a/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
+++ 
b/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
@@ -117,7 +117,8 @@ public enum TransformFunctionType {
       ReturnTypes.cascade(opBinding -> 
positionalReturnTypeInferenceFromStringLiteral(opBinding, 2,
           SqlTypeName.VARCHAR), SqlTypeTransforms.FORCE_NULLABLE),
       OperandTypes.family(ImmutableList.of(SqlTypeFamily.ANY, 
SqlTypeFamily.CHARACTER, SqlTypeFamily.CHARACTER,
-          SqlTypeFamily.CHARACTER), ordinal -> ordinal > 2), 
"json_extract_index"),
+          SqlTypeFamily.CHARACTER, SqlTypeFamily.CHARACTER), ordinal -> 
ordinal > 2), "json_extract_index"),
+
   JSON_EXTRACT_KEY("jsonExtractKey", ReturnTypes.TO_ARRAY,
       OperandTypes.family(ImmutableList.of(SqlTypeFamily.ANY, 
SqlTypeFamily.CHARACTER)), "json_extract_key"),
 
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunction.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunction.java
index 160ed36b0f..12e38ea5d6 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunction.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunction.java
@@ -53,11 +53,11 @@ public class JsonExtractIndexTransformFunction extends 
BaseTransformFunction {
 
   @Override
   public void init(List<TransformFunction> arguments, Map<String, 
ColumnContext> columnContextMap) {
-    // Check that there are exactly 3 or 4 arguments
-    if (arguments.size() < 3 || arguments.size() > 4) {
+    // Check that there are exactly 3 or 4 or 5 arguments
+    if (arguments.size() < 3 || arguments.size() > 5) {
       throw new IllegalArgumentException(
-          "Expected 3/4 arguments for transform function: 
jsonExtractIndex(jsonFieldName, 'jsonPath', 'resultsType',"
-              + " ['defaultValue'])");
+          "Expected 3/4/5 arguments for transform function: 
jsonExtractIndex(jsonFieldName, 'jsonPath', 'resultsType',"
+              + " ['defaultValue'], ['jsonFilterExpression'])");
     }
 
     TransformFunction firstArgument = arguments.get(0);
@@ -76,13 +76,12 @@ public class JsonExtractIndexTransformFunction extends 
BaseTransformFunction {
     if (!(secondArgument instanceof LiteralTransformFunction)) {
       throw new IllegalArgumentException("JSON path argument must be a 
literal");
     }
-    String inputJsonPath = ((LiteralTransformFunction) 
secondArgument).getStringLiteral();
+    _jsonPathString = ((LiteralTransformFunction) 
secondArgument).getStringLiteral();
     try {
-      JsonPathCache.INSTANCE.getOrCompute(inputJsonPath);
+      JsonPathCache.INSTANCE.getOrCompute(_jsonPathString);
     } catch (Exception e) {
       throw new IllegalArgumentException("JSON path argument is not a valid 
JSON path");
     }
-    _jsonPathString = inputJsonPath.substring(1); // remove $ prefix
 
     TransformFunction thirdArgument = arguments.get(2);
     if (!(thirdArgument instanceof LiteralTransformFunction)) {
@@ -90,14 +89,14 @@ public class JsonExtractIndexTransformFunction extends 
BaseTransformFunction {
     }
     String resultsType = ((LiteralTransformFunction) 
thirdArgument).getStringLiteral().toUpperCase();
     boolean isSingleValue = !resultsType.endsWith("_ARRAY");
-    if (isSingleValue && inputJsonPath.contains("[*]")) {
+    if (isSingleValue && _jsonPathString.contains("[*]")) {
       throw new IllegalArgumentException(
           "[*] syntax in json path is unsupported for singleValue field 
json_extract_index");
     }
     DataType dataType = isSingleValue ? DataType.valueOf(resultsType)
         : DataType.valueOf(resultsType.substring(0, resultsType.length() - 6));
 
-    if (arguments.size() == 4) {
+    if (arguments.size() >= 4) {
       TransformFunction fourthArgument = arguments.get(3);
       if (!(fourthArgument instanceof LiteralTransformFunction)) {
         throw new IllegalArgumentException("Default value must be a literal");
@@ -105,8 +104,17 @@ public class JsonExtractIndexTransformFunction extends 
BaseTransformFunction {
       _defaultValue = dataType.convert(((LiteralTransformFunction) 
fourthArgument).getStringLiteral());
     }
 
+    String filterJsonPath = null;
+    if (arguments.size() == 5) {
+      TransformFunction fifthArgument = arguments.get(4);
+      if (!(fifthArgument instanceof LiteralTransformFunction)) {
+        throw new IllegalArgumentException("JSON path filter argument must be 
a literal");
+      }
+      filterJsonPath = ((LiteralTransformFunction) 
fifthArgument).getStringLiteral();
+    }
+
     _resultMetadata = new TransformResultMetadata(dataType, isSingleValue, 
false);
-    _valueToMatchingDocsMap = 
_jsonIndexReader.getMatchingFlattenedDocsMap(_jsonPathString);
+    _valueToMatchingDocsMap = 
_jsonIndexReader.getMatchingFlattenedDocsMap(_jsonPathString, filterJsonPath);
     if (isSingleValue) {
       // For single value result type, it's more efficient to use original 
docIDs map
       _jsonIndexReader.convertFlattenedDocIdsToDocIds(_valueToMatchingDocsMap);
diff --git 
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunctionTest.java
 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunctionTest.java
index c61084c430..d2cd792107 100644
--- 
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunctionTest.java
+++ 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/JsonExtractIndexTransformFunctionTest.java
@@ -247,6 +247,23 @@ public class JsonExtractIndexTransformFunctionTest extends 
BaseTransformFunction
         String.format("jsonExtractIndex(%s,'%s','STRING_ARRAY')", 
JSON_STRING_SV_COLUMN,
             "$.arrayField[*].arrStringField"), 
"$.arrayField[*].arrStringField", DataType.STRING, false
     });
+
+    // MV with filters
+    testArguments.add(new Object[]{
+        String.format(
+            "jsonExtractIndex(%s,'%s','INT_ARRAY', '0', 
'REGEXP_LIKE(\"$.arrayField[*].arrStringField\", ''.*y.*'')')",
+            JSON_STRING_SV_COLUMN,
+            "$.arrayField[*].arrIntField"), "$.arrayField[?(@.arrStringField 
=~ /.*y.*/)].arrIntField", DataType.INT,
+        false
+    });
+
+    testArguments.add(new Object[]{
+        String.format(
+            "jsonExtractIndex(%s,'%s','STRING_ARRAY', '0', 
'\"$.arrayField[*].arrIntField\" > 2')",
+            JSON_STRING_SV_COLUMN,
+            "$.arrayField[*].arrStringField"), "$.arrayField[?(@.arrIntField > 
2)].arrStringField", DataType.STRING,
+        false
+    });
   }
 
   @Test(dataProvider = "testJsonExtractIndexDefaultValue")
diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java
index 8a5ca799cd..2f8cff69da 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java
@@ -33,6 +33,7 @@ import java.util.PriorityQueue;
 import java.util.TreeMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.regex.Pattern;
+import javax.annotation.Nullable;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.pinot.common.request.context.ExpressionContext;
 import org.apache.pinot.common.request.context.FilterContext;
@@ -367,10 +368,32 @@ public class MutableJsonIndexImpl implements 
MutableJsonIndex {
   }
 
   @Override
-  public Map<String, RoaringBitmap> getMatchingFlattenedDocsMap(String 
jsonPathKey) {
+  public Map<String, RoaringBitmap> getMatchingFlattenedDocsMap(String 
jsonPathKey, @Nullable String filterString) {
     Map<String, RoaringBitmap> valueToMatchingFlattenedDocIdsMap = new 
HashMap<>();
     _readLock.lock();
     try {
+      RoaringBitmap filteredFlattenedDocIds = null;
+      FilterContext filter;
+      if (filterString != null) {
+        filter = 
RequestContextUtils.getFilter(CalciteSqlParser.compileToExpression(filterString));
+        Preconditions.checkArgument(!filter.isConstant(), "Invalid json match 
filter: " + filterString);
+        if (filter.getType() == FilterContext.Type.PREDICATE && 
isExclusive(filter.getPredicate().getType())) {
+          // Handle exclusive predicate separately because the flip can only 
be applied to the
+          // unflattened doc ids in order to get the correct result, and it 
cannot be nested
+          filteredFlattenedDocIds = 
getMatchingFlattenedDocIds(filter.getPredicate());
+          filteredFlattenedDocIds.flip(0, (long) _nextFlattenedDocId);
+        } else {
+          filteredFlattenedDocIds = getMatchingFlattenedDocIds(filter);
+        }
+      }
+      // Support 2 formats:
+      // - JSONPath format (e.g. "$.a[1].b"='abc', "$[0]"=1, "$"='abc')
+      // - Legacy format (e.g. "a[1].b"='abc')
+      if (jsonPathKey.startsWith("$")) {
+        jsonPathKey = jsonPathKey.substring(1);
+      } else {
+        jsonPathKey = JsonUtils.KEY_SEPARATOR + jsonPathKey;
+      }
       Pair<String, RoaringBitmap> result = 
getKeyAndFlattenedDocIds(jsonPathKey);
       jsonPathKey = result.getLeft();
       RoaringBitmap arrayIndexFlattenDocIds = result.getRight();
@@ -380,6 +403,9 @@ public class MutableJsonIndexImpl implements 
MutableJsonIndex {
       Map<String, RoaringBitmap> subMap = getMatchingKeysMap(jsonPathKey);
       for (Map.Entry<String, RoaringBitmap> entry : subMap.entrySet()) {
         RoaringBitmap flattenedDocIds = entry.getValue().clone();
+        if (filteredFlattenedDocIds != null) {
+          flattenedDocIds.and(filteredFlattenedDocIds);
+        }
         if (arrayIndexFlattenDocIds != null) {
           flattenedDocIds.and(arrayIndexFlattenDocIds);
         }
diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java
index 9af37b50fb..2d67309a38 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java
@@ -28,6 +28,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.PriorityQueue;
 import java.util.regex.Pattern;
+import javax.annotation.Nullable;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.pinot.common.request.context.ExpressionContext;
 import org.apache.pinot.common.request.context.FilterContext;
@@ -134,7 +135,8 @@ public class ImmutableJsonIndexReader implements 
JsonIndexReader {
       case AND: {
         List<FilterContext> children = filter.getChildren();
         int numChildren = children.size();
-        MutableRoaringBitmap matchingDocIds = 
getMatchingFlattenedDocIds(children.get(0));
+        MutableRoaringBitmap matchingDocIds =
+            getMatchingFlattenedDocIds(children.get(0));
         for (int i = 1; i < numChildren; i++) {
           matchingDocIds.and(getMatchingFlattenedDocIds(children.get(i)));
         }
@@ -143,7 +145,8 @@ public class ImmutableJsonIndexReader implements 
JsonIndexReader {
       case OR: {
         List<FilterContext> children = filter.getChildren();
         int numChildren = children.size();
-        MutableRoaringBitmap matchingDocIds = 
getMatchingFlattenedDocIds(children.get(0));
+        MutableRoaringBitmap matchingDocIds =
+            getMatchingFlattenedDocIds(children.get(0));
         for (int i = 1; i < numChildren; i++) {
           matchingDocIds.or(getMatchingFlattenedDocIds(children.get(i)));
         }
@@ -331,7 +334,40 @@ public class ImmutableJsonIndexReader implements 
JsonIndexReader {
   }
 
   @Override
-  public Map<String, RoaringBitmap> getMatchingFlattenedDocsMap(String 
jsonPathKey) {
+  public Map<String, RoaringBitmap> getMatchingFlattenedDocsMap(String 
jsonPathKey, @Nullable String filterString) {
+    RoaringBitmap filteredFlattenedDocIds = null;
+    if (filterString != null) {
+      FilterContext filter;
+      try {
+        filter = 
RequestContextUtils.getFilter(CalciteSqlParser.compileToExpression(filterString));
+        Preconditions.checkArgument(!filter.isConstant());
+      } catch (Exception e) {
+        throw new BadQueryRequestException("Invalid json match filter: " + 
filterString);
+      }
+      if (filter.getType() == FilterContext.Type.PREDICATE && 
isExclusive(filter.getPredicate().getType())) {
+        // Handle exclusive predicate separately because the flip can only be 
applied to the
+        // unflattened doc ids in order to get the correct result, and it 
cannot be nested
+        filteredFlattenedDocIds = 
getMatchingFlattenedDocIds(filter.getPredicate()).toRoaringBitmap();
+        filteredFlattenedDocIds.flip(0, _numFlattenedDocs);
+      } else {
+        filteredFlattenedDocIds = 
getMatchingFlattenedDocIds(filter).toRoaringBitmap();
+      }
+    }
+    // Support 2 formats:
+    // - JSONPath format (e.g. "$.a[1].b"='abc', "$[0]"=1, "$"='abc')
+    // - Legacy format (e.g. "a[1].b"='abc')
+    if (_version == BaseJsonIndexCreator.VERSION_2) {
+      if (jsonPathKey.startsWith("$")) {
+        jsonPathKey = jsonPathKey.substring(1);
+      } else {
+        jsonPathKey = JsonUtils.KEY_SEPARATOR + jsonPathKey;
+      }
+    } else {
+      // For V1 backward-compatibility
+      if (jsonPathKey.startsWith("$.")) {
+        jsonPathKey = jsonPathKey.substring(2);
+      }
+    }
     Map<String, RoaringBitmap> result = new HashMap<>();
     Pair<String, MutableRoaringBitmap> pathKey = 
getKeyAndFlattenedDocIds(jsonPathKey);
     if (pathKey.getRight() != null && pathKey.getRight().isEmpty()) {
@@ -347,6 +383,10 @@ public class ImmutableJsonIndexReader implements 
JsonIndexReader {
     for (int dictId = dictIds[0]; dictId < dictIds[1]; dictId++) {
       String key = _dictionary.getStringValue(dictId);
       RoaringBitmap docIds = 
_invertedIndex.getDocIds(dictId).toRoaringBitmap();
+      if (filteredFlattenedDocIds != null) {
+        docIds.and(filteredFlattenedDocIds);
+      }
+
       if (arrayIndexFlattenDocIds != null) {
         docIds.and(arrayIndexFlattenDocIds);
       }
diff --git 
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java
 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java
index 1b2a910da3..14f8a79bc1 100644
--- 
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java
+++ 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java
@@ -347,9 +347,21 @@ public class JsonIndexTest {
     // CHECKSTYLE:ON
     // @formatter: on
 
-    String[] testKeys = new String[]{
-        ".arrField[*].intKey01",
-        ".arrField[*].stringKey01",
+    String[][] testKeys = new String[][]{
+        // Without filters
+        {"$.arrField[*].intKey01", null},
+        {"$.arrField[*].stringKey01", null},
+
+        // With regexp filter
+        {"$.arrField[*].intKey01", "REGEXP_LIKE(\"arrField..stringKey01\", 
'.*f.*')"},
+        // With range filter
+        {"$.arrField[*].stringKey01", "\"arrField..intKey01\" > 2"},
+        // With AND filters
+        {"$.arrField[*].intKey01", "\"arrField..intKey01\" > 2 AND 
REGEXP_LIKE(\"arrField..stringKey01\", "
+            + "'[a-b][a-b].*')"},
+        // Exclusive filters
+        {"$.arrField[*].intKey01", "\"arrField[*].stringKey01\" != 'bar'"},
+        {"$.arrField[*].stringKey01", "\"arrField[*].intKey01\" != '3'"},
     };
 
     String colName = "col";
@@ -371,18 +383,23 @@ public class JsonIndexTest {
         int docIdValidLength = 2;
         String[][][] expectedValues = new String[][][]{
             {{"1", "1", "3", "5"}, {"1", "1", "6", "3"}},
-            {{"abc", "foo", "bar", "fuzz"}, {"pqr", "foo", "test", "testf2"}}
+            {{"abc", "foo", "bar", "fuzz"}, {"pqr", "foo", "test", "testf2"}},
+            {{"1", "5"}, {"1", "3"}},
+            {{"bar", "fuzz"}, {"test", "testf2"}},
+            {{"3"}, {}},
+            {{"1", "1", "5"}, {"1", "1", "6", "3"}},
+            {{"abc", "foo", "fuzz"}, {"pqr", "foo", "test"}}
         };
         for (int i = 0; i < testKeys.length; i++) {
           Map<String, RoaringBitmap> context =
-              offHeapIndexReader.getMatchingFlattenedDocsMap(testKeys[i]);
+              offHeapIndexReader.getMatchingFlattenedDocsMap(testKeys[i][0], 
testKeys[i][1]);
           String[][] values = offHeapIndexReader.getValuesMV(docMask, 
docIdValidLength, context);
 
           for (int j = 0; j < docIdValidLength; j++) {
             Assert.assertEquals(values[j], expectedValues[i][j]);
           }
 
-          context = mutableJsonIndex.getMatchingFlattenedDocsMap(testKeys[i]);
+          context = 
mutableJsonIndex.getMatchingFlattenedDocsMap(testKeys[i][0], testKeys[i][1]);
           values = mutableJsonIndex.getValuesMV(docMask, docIdValidLength, 
context);
           Assert.assertEquals(values, expectedValues[i]);
         }
@@ -402,7 +419,7 @@ public class JsonIndexTest {
     };
     // CHECKSTYLE:ON
     // @formatter: on
-    String[] testKeys = new String[]{".field1", ".field2", ".field3", 
".field4"};
+    String[] testKeys = new String[]{"$.field1", "$.field2", "$.field3", 
"$.field4"};
 
     String colName = "col";
     try (
@@ -427,7 +444,7 @@ public class JsonIndexTest {
             new String[][]{{"value1", "value2", "value1"}, {"value2", null, 
"value4"}, {"value3", null, null},
                 {null, null, null}};
         for (int i = 0; i < testKeys.length; i++) {
-          Map<String, RoaringBitmap> context = 
offHeapIndexReader.getMatchingFlattenedDocsMap(testKeys[i]);
+          Map<String, RoaringBitmap> context = 
offHeapIndexReader.getMatchingFlattenedDocsMap(testKeys[i], null);
           String[] values = offHeapIndexReader.getValuesSV(docMask, 
docMask.length, context, true);
           Assert.assertEquals(values, expectedValues[i]);
 
@@ -435,7 +452,7 @@ public class JsonIndexTest {
           values = offHeapIndexReader.getValuesSV(docMask, docMask.length, 
context, false);
           Assert.assertEquals(values, expectedValues[i]);
 
-          context = mutableJsonIndex.getMatchingFlattenedDocsMap(testKeys[i]);
+          context = mutableJsonIndex.getMatchingFlattenedDocsMap(testKeys[i], 
null);
           values = mutableJsonIndex.getValuesSV(docMask, docMask.length, 
context, true);
           Assert.assertEquals(values, expectedValues[i]);
 
@@ -448,7 +465,7 @@ public class JsonIndexTest {
         docMask = new int[]{1, 2};
         expectedValues = new String[][]{{"value2", "value1"}, {null, 
"value4"}, {null, null}, {null, null}};
         for (int i = 0; i < testKeys.length; i++) {
-          Map<String, RoaringBitmap> context = 
offHeapIndexReader.getMatchingFlattenedDocsMap(testKeys[i]);
+          Map<String, RoaringBitmap> context = 
offHeapIndexReader.getMatchingFlattenedDocsMap(testKeys[i], null);
           String[] values = offHeapIndexReader.getValuesSV(docMask, 
docMask.length, context, true);
           Assert.assertEquals(values, expectedValues[i]);
 
@@ -456,7 +473,7 @@ public class JsonIndexTest {
           values = offHeapIndexReader.getValuesSV(docMask, docMask.length, 
context, false);
           Assert.assertEquals(values, expectedValues[i]);
 
-          context = mutableJsonIndex.getMatchingFlattenedDocsMap(testKeys[i]);
+          context = mutableJsonIndex.getMatchingFlattenedDocsMap(testKeys[i], 
null);
           values = mutableJsonIndex.getValuesSV(docMask, docMask.length, 
context, true);
           Assert.assertEquals(values, expectedValues[i]);
 
@@ -466,7 +483,7 @@ public class JsonIndexTest {
         }
 
         // Immutable index, context is reused for the second method call
-        Map<String, RoaringBitmap> context = 
offHeapIndexReader.getMatchingFlattenedDocsMap(".field1");
+        Map<String, RoaringBitmap> context = 
offHeapIndexReader.getMatchingFlattenedDocsMap("$.field1", null);
         docMask = new int[]{0};
         String[] values = offHeapIndexReader.getValuesSV(docMask, 
docMask.length, context, true);
         Assert.assertEquals(values, new String[]{"value1"});
@@ -483,7 +500,7 @@ public class JsonIndexTest {
         Assert.assertEquals(values, new String[]{"value2", "value1"});
 
         // Mutable index, context is reused for the second method call
-        context = mutableJsonIndex.getMatchingFlattenedDocsMap(".field1");;
+        context = mutableJsonIndex.getMatchingFlattenedDocsMap("$.field1", 
null);;
         docMask = new int[]{0};
         values = mutableJsonIndex.getValuesSV(docMask, docMask.length, 
context, true);
         Assert.assertEquals(values, new String[]{"value1"});
@@ -525,9 +542,9 @@ public class JsonIndexTest {
       for (String record : records) {
         mutableJsonIndex.add(record);
       }
-      Map<String, RoaringBitmap> onHeapRes = 
onHeapIndexReader.getMatchingFlattenedDocsMap("");
-      Map<String, RoaringBitmap> offHeapRes = 
offHeapIndexReader.getMatchingFlattenedDocsMap("");
-      Map<String, RoaringBitmap> mutableRes = 
mutableJsonIndex.getMatchingFlattenedDocsMap("");
+      Map<String, RoaringBitmap> onHeapRes = 
onHeapIndexReader.getMatchingFlattenedDocsMap("$", null);
+      Map<String, RoaringBitmap> offHeapRes = 
offHeapIndexReader.getMatchingFlattenedDocsMap("$", null);
+      Map<String, RoaringBitmap> mutableRes = 
mutableJsonIndex.getMatchingFlattenedDocsMap("$", null);
       Map<String, RoaringBitmap> expectedRes = 
Collections.singletonMap(JsonUtils.SKIPPED_VALUE_REPLACEMENT,
           RoaringBitmap.bitmapOf(0));
       Assert.assertEquals(expectedRes, onHeapRes);
@@ -563,8 +580,8 @@ public class JsonIndexTest {
     File offHeapIndexFile = new File(INDEX_DIR, OFF_HEAP_COLUMN_NAME + 
V1Constants.Indexes.JSON_INDEX_FILE_EXTENSION);
     Assert.assertTrue(offHeapIndexFile.exists());
 
-    String[] keys = {".foo[0].bar[1]", ".foo[1].bar[0]", ".foo2[0]", 
".foo[100].bar[100]", ".foo[0].bar[*]",
-            ".foo[*].bar[0]", ".foo[*].bar[*]"};
+    String[] keys = {"$.foo[0].bar[1]", "$.foo[1].bar[0]", "$.foo2[0]", 
"$.foo[100].bar[100]", "$.foo[0].bar[*]",
+            "$.foo[*].bar[0]", "$.foo[*].bar[*]"};
     List<Map<String, RoaringBitmap>> expected = List.of(
             Map.of("y", RoaringBitmap.bitmapOf(0), "z", 
RoaringBitmap.bitmapOf(1)),
             Map.of("a", RoaringBitmap.bitmapOf(0)),
@@ -593,11 +610,11 @@ public class JsonIndexTest {
       }
 
       for (int i = 0; i < keys.length; i++) {
-        Map<String, RoaringBitmap> onHeapRes = 
onHeapIndexReader.getMatchingFlattenedDocsMap(keys[i]);
+        Map<String, RoaringBitmap> onHeapRes = 
onHeapIndexReader.getMatchingFlattenedDocsMap(keys[i], null);
         onHeapIndexReader.convertFlattenedDocIdsToDocIds(onHeapRes);
-        Map<String, RoaringBitmap> offHeapRes = 
offHeapIndexReader.getMatchingFlattenedDocsMap(keys[i]);
+        Map<String, RoaringBitmap> offHeapRes = 
offHeapIndexReader.getMatchingFlattenedDocsMap(keys[i], null);
         offHeapIndexReader.convertFlattenedDocIdsToDocIds(offHeapRes);
-        Map<String, RoaringBitmap> mutableRes = 
mutableJsonIndex.getMatchingFlattenedDocsMap(keys[i]);
+        Map<String, RoaringBitmap> mutableRes = 
mutableJsonIndex.getMatchingFlattenedDocsMap(keys[i], null);
         mutableJsonIndex.convertFlattenedDocIdsToDocIds(mutableRes);
         Assert.assertEquals(expected.get(i), onHeapRes);
         Assert.assertEquals(expected.get(i), offHeapRes);
diff --git 
a/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/reader/JsonIndexReader.java
 
b/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/reader/JsonIndexReader.java
index 73ef8450ee..44f7dc82c6 100644
--- 
a/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/reader/JsonIndexReader.java
+++ 
b/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/reader/JsonIndexReader.java
@@ -19,6 +19,7 @@
 package org.apache.pinot.segment.spi.index.reader;
 
 import java.util.Map;
+import javax.annotation.Nullable;
 import org.apache.pinot.segment.spi.index.IndexReader;
 import org.roaringbitmap.RoaringBitmap;
 import org.roaringbitmap.buffer.MutableRoaringBitmap;
@@ -60,7 +61,7 @@ public interface JsonIndexReader extends IndexReader {
    * For a JSON key, returns a Map from each value to the flattened docId 
posting list. This map should be used to
    * avoid reading and converting the posting list of flattened docIds to real 
docIds
    */
-  Map<String, RoaringBitmap> getMatchingFlattenedDocsMap(String key);
+  Map<String, RoaringBitmap> getMatchingFlattenedDocsMap(String key, @Nullable 
String filterJsonString);
 
   /**
    * Converts the flattened docIds to real docIds using the map returned by 
getMatchingFlattenedDocsMap


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to