You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by "xiangfu0 (via GitHub)" <gi...@apache.org> on 2026/08/19 00:25:42 UTC
[PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
xiangfu0 opened a new pull request, #19297:
URL: https://github.com/apache/pinot/pull/19297
Part 1/5 of the split of #19287 (Fix FULL-upsert vector candidate generation).
## Summary
Groundwork for applying the FULL-upsert valid-document snapshot before vector candidate
selection (done in part 4/5):
- Extract a shared `computeExactMatches` helper in `ExactVectorScanFilterOperator` that
unifies the exact top-K and threshold scan paths and can restrict scoring to an
allowed-document bitmap. When a bitmap is supplied, only allowed document IDs are read
from the forward index, and IDs beyond the `numDocs` watermark are ignored.
- Introduce `VectorCandidateScope`, an immutable query-scoped candidate constraint that
owns a single defensive copy of the supplied bitmap. `ExactVectorScanFilterOperator`
accepts it via a new constructor overload; no production caller passes one yet, so
behavior is unchanged.
- Report candidate-filter cardinality in the operator's explain output.
- Add filtered-reader coverage for `HnswVectorIndexReader.getDocIds(query, k, allowed)`.
## Validation
All commands ran with JDK 25.
- `ExactVectorScanFilterOperatorTest`: 16 tests passed (6 new allowed-document tests).
- `HnswVectorIndexCreatorTest`: 6 tests passed (1 new filtered-reader test).
- Spotless, Checkstyle, and license checks passed.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "Jackie-Jiang (via GitHub)" <gi...@apache.org>.
Jackie-Jiang commented on code in PR #19297:
URL: https://github.com/apache/pinot/pull/19297#discussion_r3865199266
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -74,28 +79,21 @@ public class ExactVectorScanFilterOperator extends BaseFilterOperator {
/// @param predicate the vector similarity predicate containing query vector and top-K
/// @param column the column name (for logging and explain)
/// @param numDocs the total number of documents in the segment
- public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
- VectorSimilarityPredicate predicate, String column, int numDocs) {
- this(forwardIndexReader, predicate, column, numDocs, null, "vector_index_missing",
- VectorSearchParams.DEFAULT);
- }
-
+ /// @param vectorIndexConfig vector index configuration, used to resolve the distance function (may be null)
+ /// @param fallbackReason why this scan runs instead of an ANN search, reported in explain output
+ /// @param searchParams vector search parameters from query options
+ /// @param candidateScope documents this scan may consider, or null to scan the whole segment
public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
VectorSimilarityPredicate predicate, String column, int numDocs, @Nullable VectorIndexConfig vectorIndexConfig,
- String fallbackReason) {
- this(forwardIndexReader, predicate, column, numDocs, vectorIndexConfig, fallbackReason,
- VectorSearchParams.DEFAULT);
- }
-
- public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
- VectorSimilarityPredicate predicate, String column, int numDocs, @Nullable VectorIndexConfig vectorIndexConfig,
- String fallbackReason, VectorSearchParams searchParams) {
+ String fallbackReason, VectorSearchParams searchParams,
+ @Nullable VectorCandidateScope candidateScope) {
Review Comment:
(nit) Reformat
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorCandidateScope.java:
##########
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+package org.apache.pinot.core.operator.filter;
+
+import com.google.common.base.Preconditions;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+
+
+/// Immutable set of document IDs a vector predicate is allowed to consider as candidates.
+///
+/// Vector top-K is not monotonic: unlike an ordinary predicate, restricting the corpus changes which documents win
+/// the top-K contest, so a document set that defines what the query may see must be applied *before* candidate
+/// generation rather than intersected with the result afterwards. That contract is the entire meaning of this type.
+/// It deliberately says nothing about where the restriction came from -- callers such as [FilterPlanNode] decide
+/// that, today from the segment's queryable-document snapshot.
+///
+/// Contrast with the optimizer-selected metadata bitmap passed to
+/// [VectorSimilarityFilterOperator#setPreFilterBitmap]: that one is optional, because post-filtering an ordinary
+/// predicate is already correct and pre-filtering only improves recall.
+///
+/// The factory owns the single detached copy of the supplied bitmap, so operators can share a scope freely and only
+/// allocate again when they intersect it with an independent optional filter.
+public final class VectorCandidateScope {
+ private final ImmutableRoaringBitmap _requiredDocIds;
+
+ private VectorCandidateScope(ImmutableRoaringBitmap requiredDocIds) {
+ // Detach from the caller's bitmap so candidate generation and the outer valid-document AND observe the same
+ // document set for the whole query. Copying into array-backed containers keeps per-document `contains` checks
+ // cheap, which matters because filtered graph traversal probes this bitmap once per visited node.
+ _requiredDocIds = requiredDocIds.toMutableRoaringBitmap().toImmutableRoaringBitmap();
+ }
+
+ /// Creates a scope from the document IDs the query is allowed to consider.
+ public static VectorCandidateScope of(ImmutableRoaringBitmap requiredDocIds) {
Review Comment:
(minor) Do we need this? Seems a public constructor is good enough
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorCandidateScope.java:
##########
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+package org.apache.pinot.core.operator.filter;
+
+import com.google.common.base.Preconditions;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+
+
+/// Immutable set of document IDs a vector predicate is allowed to consider as candidates.
+///
+/// Vector top-K is not monotonic: unlike an ordinary predicate, restricting the corpus changes which documents win
+/// the top-K contest, so a document set that defines what the query may see must be applied *before* candidate
+/// generation rather than intersected with the result afterwards. That contract is the entire meaning of this type.
+/// It deliberately says nothing about where the restriction came from -- callers such as [FilterPlanNode] decide
+/// that, today from the segment's queryable-document snapshot.
+///
+/// Contrast with the optimizer-selected metadata bitmap passed to
+/// [VectorSimilarityFilterOperator#setPreFilterBitmap]: that one is optional, because post-filtering an ordinary
+/// predicate is already correct and pre-filtering only improves recall.
+///
+/// The factory owns the single detached copy of the supplied bitmap, so operators can share a scope freely and only
+/// allocate again when they intersect it with an independent optional filter.
+public final class VectorCandidateScope {
Review Comment:
Are we planning to extend this to include more context? Seems the name of the class indicates it is just a bitmap. Directly passing in a bitmap could be more clear
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorCandidateScope.java:
##########
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+package org.apache.pinot.core.operator.filter;
+
+import com.google.common.base.Preconditions;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+
+
+/// Immutable set of document IDs a vector predicate is allowed to consider as candidates.
+///
+/// Vector top-K is not monotonic: unlike an ordinary predicate, restricting the corpus changes which documents win
+/// the top-K contest, so a document set that defines what the query may see must be applied *before* candidate
+/// generation rather than intersected with the result afterwards. That contract is the entire meaning of this type.
+/// It deliberately says nothing about where the restriction came from -- callers such as [FilterPlanNode] decide
+/// that, today from the segment's queryable-document snapshot.
+///
+/// Contrast with the optimizer-selected metadata bitmap passed to
+/// [VectorSimilarityFilterOperator#setPreFilterBitmap]: that one is optional, because post-filtering an ordinary
+/// predicate is already correct and pre-filtering only improves recall.
+///
+/// The factory owns the single detached copy of the supplied bitmap, so operators can share a scope freely and only
+/// allocate again when they intersect it with an independent optional filter.
+public final class VectorCandidateScope {
+ private final ImmutableRoaringBitmap _requiredDocIds;
+
+ private VectorCandidateScope(ImmutableRoaringBitmap requiredDocIds) {
+ // Detach from the caller's bitmap so candidate generation and the outer valid-document AND observe the same
+ // document set for the whole query. Copying into array-backed containers keeps per-document `contains` checks
+ // cheap, which matters because filtered graph traversal probes this bitmap once per visited node.
+ _requiredDocIds = requiredDocIds.toMutableRoaringBitmap().toImmutableRoaringBitmap();
Review Comment:
Why doing so? I don't follow the comment
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "Jackie-Jiang (via GitHub)" <gi...@apache.org>.
Jackie-Jiang commented on code in PR #19297:
URL: https://github.com/apache/pinot/pull/19297#discussion_r3817150307
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -90,12 +94,21 @@ public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
VectorSimilarityPredicate predicate, String column, int numDocs, @Nullable VectorIndexConfig vectorIndexConfig,
String fallbackReason, VectorSearchParams searchParams) {
+ this(forwardIndexReader, predicate, column, numDocs, vectorIndexConfig, fallbackReason, searchParams, null);
+ }
+
+ /// Creates an exact scan restricted to a mandatory query-owned candidate scope.
+ public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
Review Comment:
We got too many constructors, where only the main one is used in production. Let's just keep one constructor and make test put all the arguments
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -90,12 +94,21 @@ public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
VectorSimilarityPredicate predicate, String column, int numDocs, @Nullable VectorIndexConfig vectorIndexConfig,
String fallbackReason, VectorSearchParams searchParams) {
+ this(forwardIndexReader, predicate, column, numDocs, vectorIndexConfig, fallbackReason, searchParams, null);
+ }
+
+ /// Creates an exact scan restricted to a mandatory query-owned candidate scope.
+ public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
Review Comment:
Is this used? Seems there is no change to `FilterPlanNode`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "xiangfu0 (via GitHub)" <gi...@apache.org>.
xiangfu0 commented on code in PR #19297:
URL: https://github.com/apache/pinot/pull/19297#discussion_r3849650322
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -169,87 +184,113 @@ protected void explainAttributes(ExplainAttributeBuilder attributeBuilder) {
attributeBuilder.putString("vectorLiteral", Arrays.toString(_predicate.getValue()));
attributeBuilder.putString("fallbackReason", _vectorExplainContext.getFallbackReason());
attributeBuilder.putLongIdempotent("topKtoSearch", _predicate.getTopK());
+ attributeBuilder.putBool("upsertCandidateFilterApplied", _requiredUpsertCandidateBitmap != null);
+ attributeBuilder.putLongIdempotent("upsertCandidateFilterCardinality", getRequiredUpsertCandidateCardinality());
+ attributeBuilder.putLongIdempotent("effectiveAllowedDocIdsCardinality",
+ getEffectiveAllowedDocIdsCardinality());
Review Comment:
Switched both cardinality attributes to additive `putLong` (matching `annCandidateCount`/`rerankedCandidateCount`), so differing per-segment valid-doc counts no longer block `PlanNodeMerger`. They are still only emitted when a candidate scope is present. Applied the same fix to `VectorSimilarityFilterOperator` in the 4/5 PR, which adds the equivalent attributes.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -169,87 +184,113 @@ protected void explainAttributes(ExplainAttributeBuilder attributeBuilder) {
attributeBuilder.putString("vectorLiteral", Arrays.toString(_predicate.getValue()));
attributeBuilder.putString("fallbackReason", _vectorExplainContext.getFallbackReason());
attributeBuilder.putLongIdempotent("topKtoSearch", _predicate.getTopK());
+ attributeBuilder.putBool("upsertCandidateFilterApplied", _requiredUpsertCandidateBitmap != null);
+ attributeBuilder.putLongIdempotent("upsertCandidateFilterCardinality", getRequiredUpsertCandidateCardinality());
+ attributeBuilder.putLongIdempotent("effectiveAllowedDocIdsCardinality",
+ getEffectiveAllowedDocIdsCardinality());
}
/// Performs brute-force exact search over all documents in the segment.
/// When a distance threshold is set, returns all vectors within the threshold.
/// Otherwise uses a max-heap to maintain the top-K closest vectors.
- @SuppressWarnings("unchecked")
private ImmutableRoaringBitmap computeExactTopK() {
+ ImmutableRoaringBitmap allowedDocIds = _requiredUpsertCandidateBitmap;
+ if (allowedDocIds != null && allowedDocIds.isEmpty()) {
+ return new MutableRoaringBitmap();
+ }
LOGGER.warn("Performing exact vector scan fallback on column: {} for segment with {} docs. "
- + "reason={}, distanceFunction={}, hasThreshold={}. "
+ + "reason={}, distanceFunction={}, hasThreshold={}, allowedDocs={}. "
+ "This is expensive -- consider adding a vector index.",
_column, _numDocs, _vectorExplainContext.getFallbackReason(),
- _vectorExplainContext.getDistanceFunction(), _hasDistanceThreshold);
+ _vectorExplainContext.getDistanceFunction(), _hasDistanceThreshold,
+ allowedDocIds != null ? allowedDocIds.getCardinality() : _numDocs);
float[] queryVector = _predicate.getValue();
+ Float threshold = _hasDistanceThreshold ? _distanceThreshold : null;
+ ImmutableRoaringBitmap result = computeExactMatches(_forwardIndexReader, queryVector, _predicate.getTopK(),
+ _numDocs, _vectorExplainContext.getDistanceFunction(), threshold, allowedDocIds, _column);
- if (_hasDistanceThreshold) {
- return computeExactThreshold(queryVector);
- }
+ LOGGER.debug("Exact vector scan on column: {} returned {} results from {} docs",
+ _column, result.getCardinality(), _numDocs);
- int topK = _predicate.getTopK();
+ return result;
+ }
- // Max-heap: entry with largest distance is at the top so we can efficiently evict it
- PriorityQueue<DocDistance> maxHeap = new PriorityQueue<>(topK + 1,
- (a, b) -> Float.compare(b._distance, a._distance));
+ /// Performs an exact top-K or threshold search over all documents or the supplied allowed-document bitmap.
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ static ImmutableRoaringBitmap computeExactMatches(ForwardIndexReader<?> forwardIndexReader,
+ float[] queryVector, int topK, int numDocs,
+ VectorIndexConfig.VectorDistanceFunction distanceFunction, @Nullable Float distanceThreshold,
+ @Nullable ImmutableRoaringBitmap allowedDocIds, String column) {
+ if ((allowedDocIds != null && allowedDocIds.isEmpty()) || (distanceThreshold == null && topK <= 0)) {
+ return new MutableRoaringBitmap();
Review Comment:
Good catch — `topK` comes straight from the query literal with no parse-time validation, so this was reachable and inconsistent. Top-K mode now does `Preconditions.checkArgument(topK > 0, ...)`, matching `IvfFlatVectorIndexReader`/`IvfPqVectorIndexReader`/`IvfOnDiskVectorIndexReader`; threshold mode still ignores `topK`. Updated the test to expect the error and added one covering threshold search with a non-positive `topK`.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #19297:
URL: https://github.com/apache/pinot/pull/19297#discussion_r3809288724
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -169,87 +184,113 @@ protected void explainAttributes(ExplainAttributeBuilder attributeBuilder) {
attributeBuilder.putString("vectorLiteral", Arrays.toString(_predicate.getValue()));
attributeBuilder.putString("fallbackReason", _vectorExplainContext.getFallbackReason());
attributeBuilder.putLongIdempotent("topKtoSearch", _predicate.getTopK());
+ attributeBuilder.putBool("upsertCandidateFilterApplied", _requiredUpsertCandidateBitmap != null);
+ attributeBuilder.putLongIdempotent("upsertCandidateFilterCardinality", getRequiredUpsertCandidateCardinality());
+ attributeBuilder.putLongIdempotent("effectiveAllowedDocIdsCardinality",
+ getEffectiveAllowedDocIdsCardinality());
Review Comment:
These cardinalities vary per segment, so marking them `IDEMPOTENT` prevents `PlanNodeMerger` from merging exact-scan nodes whenever valid-document counts differ; `IDEMPOTENT` values merge only when equal (`PlanNodeMerger.java:74-77`). Runtime candidate counts use additive `putLong` instead (`VectorSimilarityFilterOperator.java:286,289`). Emit additive cardinalities only when a candidate scope exists, otherwise large explains can expand to one node per segment.
This issue also appears on line 292 of the same file.
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -169,87 +184,113 @@ protected void explainAttributes(ExplainAttributeBuilder attributeBuilder) {
attributeBuilder.putString("vectorLiteral", Arrays.toString(_predicate.getValue()));
attributeBuilder.putString("fallbackReason", _vectorExplainContext.getFallbackReason());
attributeBuilder.putLongIdempotent("topKtoSearch", _predicate.getTopK());
+ attributeBuilder.putBool("upsertCandidateFilterApplied", _requiredUpsertCandidateBitmap != null);
+ attributeBuilder.putLongIdempotent("upsertCandidateFilterCardinality", getRequiredUpsertCandidateCardinality());
+ attributeBuilder.putLongIdempotent("effectiveAllowedDocIdsCardinality",
+ getEffectiveAllowedDocIdsCardinality());
}
/// Performs brute-force exact search over all documents in the segment.
/// When a distance threshold is set, returns all vectors within the threshold.
/// Otherwise uses a max-heap to maintain the top-K closest vectors.
- @SuppressWarnings("unchecked")
private ImmutableRoaringBitmap computeExactTopK() {
+ ImmutableRoaringBitmap allowedDocIds = _requiredUpsertCandidateBitmap;
+ if (allowedDocIds != null && allowedDocIds.isEmpty()) {
+ return new MutableRoaringBitmap();
+ }
LOGGER.warn("Performing exact vector scan fallback on column: {} for segment with {} docs. "
- + "reason={}, distanceFunction={}, hasThreshold={}. "
+ + "reason={}, distanceFunction={}, hasThreshold={}, allowedDocs={}. "
+ "This is expensive -- consider adding a vector index.",
_column, _numDocs, _vectorExplainContext.getFallbackReason(),
- _vectorExplainContext.getDistanceFunction(), _hasDistanceThreshold);
+ _vectorExplainContext.getDistanceFunction(), _hasDistanceThreshold,
+ allowedDocIds != null ? allowedDocIds.getCardinality() : _numDocs);
float[] queryVector = _predicate.getValue();
+ Float threshold = _hasDistanceThreshold ? _distanceThreshold : null;
+ ImmutableRoaringBitmap result = computeExactMatches(_forwardIndexReader, queryVector, _predicate.getTopK(),
+ _numDocs, _vectorExplainContext.getDistanceFunction(), threshold, allowedDocIds, _column);
- if (_hasDistanceThreshold) {
- return computeExactThreshold(queryVector);
- }
+ LOGGER.debug("Exact vector scan on column: {} returned {} results from {} docs",
+ _column, result.getCardinality(), _numDocs);
- int topK = _predicate.getTopK();
+ return result;
+ }
- // Max-heap: entry with largest distance is at the top so we can efficiently evict it
- PriorityQueue<DocDistance> maxHeap = new PriorityQueue<>(topK + 1,
- (a, b) -> Float.compare(b._distance, a._distance));
+ /// Performs an exact top-K or threshold search over all documents or the supplied allowed-document bitmap.
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ static ImmutableRoaringBitmap computeExactMatches(ForwardIndexReader<?> forwardIndexReader,
+ float[] queryVector, int topK, int numDocs,
+ VectorIndexConfig.VectorDistanceFunction distanceFunction, @Nullable Float distanceThreshold,
+ @Nullable ImmutableRoaringBitmap allowedDocIds, String column) {
+ if ((allowedDocIds != null && allowedDocIds.isEmpty()) || (distanceThreshold == null && topK <= 0)) {
+ return new MutableRoaringBitmap();
Review Comment:
Non-positive `topK` is now silently converted to an empty result, while indexed backends reject it (for example, `IvfFlatVectorIndexReader.java:212` and `IvfPqVectorIndexReader.java:164`). The same `VECTOR_SIMILARITY` query can therefore fail or return no rows depending on whether a segment uses exact fallback. In top-K mode, validate `topK > 0` before the empty-bitmap shortcut and update the new test to expect that validation error; threshold mode can continue to ignore `topK`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "xiangfu0 (via GitHub)" <gi...@apache.org>.
xiangfu0 commented on code in PR #19297:
URL: https://github.com/apache/pinot/pull/19297#discussion_r3849651065
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -90,12 +94,21 @@ public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
VectorSimilarityPredicate predicate, String column, int numDocs, @Nullable VectorIndexConfig vectorIndexConfig,
String fallbackReason, VectorSearchParams searchParams) {
+ this(forwardIndexReader, predicate, column, numDocs, vectorIndexConfig, fallbackReason, searchParams, null);
+ }
+
+ /// Creates an exact scan restricted to a mandatory query-owned candidate scope.
+ public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
Review Comment:
Collapsed to a single constructor — the three convenience overloads are gone and the tests now pass every argument.
On the second question: `FilterPlanNode` does call it (the no-index exact-scan path), it just was not visible in the diff because the old overload defaulted the trailing arguments. It now passes `null` for the candidate scope explicitly, so the call site shows the full signature.
The scope parameter itself is unused in production *in this PR* by design: this is 1/5 of a stack splitting #19287. The scope is what lets an exact scan restrict itself to a document set, and #19300 (4/5) is where `FilterPlanNode` starts passing a real one — it is the fix for FULL-upsert vector queries, where obsolete row versions must not consume the per-segment top-K budget. It is here in 1/5 because the allowed-document scan logic and its tests belong with the `computeExactMatches` refactor. Happy to fold it into 4/5 instead if you would rather 1/5 carry no unused parameter.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "xiangfu0 (via GitHub)" <gi...@apache.org>.
xiangfu0 commented on code in PR #19297:
URL: https://github.com/apache/pinot/pull/19297#discussion_r3865278773
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/ExactVectorScanFilterOperator.java:
##########
@@ -74,28 +79,21 @@ public class ExactVectorScanFilterOperator extends BaseFilterOperator {
/// @param predicate the vector similarity predicate containing query vector and top-K
/// @param column the column name (for logging and explain)
/// @param numDocs the total number of documents in the segment
- public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
- VectorSimilarityPredicate predicate, String column, int numDocs) {
- this(forwardIndexReader, predicate, column, numDocs, null, "vector_index_missing",
- VectorSearchParams.DEFAULT);
- }
-
+ /// @param vectorIndexConfig vector index configuration, used to resolve the distance function (may be null)
+ /// @param fallbackReason why this scan runs instead of an ANN search, reported in explain output
+ /// @param searchParams vector search parameters from query options
+ /// @param candidateScope documents this scan may consider, or null to scan the whole segment
public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
VectorSimilarityPredicate predicate, String column, int numDocs, @Nullable VectorIndexConfig vectorIndexConfig,
- String fallbackReason) {
- this(forwardIndexReader, predicate, column, numDocs, vectorIndexConfig, fallbackReason,
- VectorSearchParams.DEFAULT);
- }
-
- public ExactVectorScanFilterOperator(ForwardIndexReader<?> forwardIndexReader,
- VectorSimilarityPredicate predicate, String column, int numDocs, @Nullable VectorIndexConfig vectorIndexConfig,
- String fallbackReason, VectorSearchParams searchParams) {
+ String fallbackReason, VectorSearchParams searchParams,
+ @Nullable VectorCandidateScope candidateScope) {
Review Comment:
Reformatted — the parameter list now packs to the line limit instead of breaking early.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorCandidateScope.java:
##########
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+package org.apache.pinot.core.operator.filter;
+
+import com.google.common.base.Preconditions;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+
+
+/// Immutable set of document IDs a vector predicate is allowed to consider as candidates.
+///
+/// Vector top-K is not monotonic: unlike an ordinary predicate, restricting the corpus changes which documents win
+/// the top-K contest, so a document set that defines what the query may see must be applied *before* candidate
+/// generation rather than intersected with the result afterwards. That contract is the entire meaning of this type.
+/// It deliberately says nothing about where the restriction came from -- callers such as [FilterPlanNode] decide
+/// that, today from the segment's queryable-document snapshot.
+///
+/// Contrast with the optimizer-selected metadata bitmap passed to
+/// [VectorSimilarityFilterOperator#setPreFilterBitmap]: that one is optional, because post-filtering an ordinary
+/// predicate is already correct and pre-filtering only improves recall.
+///
+/// The factory owns the single detached copy of the supplied bitmap, so operators can share a scope freely and only
+/// allocate again when they intersect it with an independent optional filter.
+public final class VectorCandidateScope {
Review Comment:
Agreed — removed the class and pass the bitmap directly.
To answer the question: there was a planned extension (a follow-up makes the mutable HNSW index filter-aware, which needs the candidate set bounded by the published-document watermark as well). But in this PR the type holds exactly one bitmap, so it is speculative generality here. If that second field actually materializes, introducing a type then will be a smaller and better-justified change than keeping an empty wrapper now.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorCandidateScope.java:
##########
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+package org.apache.pinot.core.operator.filter;
+
+import com.google.common.base.Preconditions;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+
+
+/// Immutable set of document IDs a vector predicate is allowed to consider as candidates.
+///
+/// Vector top-K is not monotonic: unlike an ordinary predicate, restricting the corpus changes which documents win
+/// the top-K contest, so a document set that defines what the query may see must be applied *before* candidate
+/// generation rather than intersected with the result afterwards. That contract is the entire meaning of this type.
+/// It deliberately says nothing about where the restriction came from -- callers such as [FilterPlanNode] decide
+/// that, today from the segment's queryable-document snapshot.
+///
+/// Contrast with the optimizer-selected metadata bitmap passed to
+/// [VectorSimilarityFilterOperator#setPreFilterBitmap]: that one is optional, because post-filtering an ordinary
+/// predicate is already correct and pre-filtering only improves recall.
+///
+/// The factory owns the single detached copy of the supplied bitmap, so operators can share a scope freely and only
+/// allocate again when they intersect it with an independent optional filter.
+public final class VectorCandidateScope {
+ private final ImmutableRoaringBitmap _requiredDocIds;
+
+ private VectorCandidateScope(ImmutableRoaringBitmap requiredDocIds) {
+ // Detach from the caller's bitmap so candidate generation and the outer valid-document AND observe the same
+ // document set for the whole query. Copying into array-backed containers keeps per-document `contains` checks
+ // cheap, which matters because filtered graph traversal probes this bitmap once per visited node.
+ _requiredDocIds = requiredDocIds.toMutableRoaringBitmap().toImmutableRoaringBitmap();
+ }
+
+ /// Creates a scope from the document IDs the query is allowed to consider.
+ public static VectorCandidateScope of(ImmutableRoaringBitmap requiredDocIds) {
Review Comment:
Moot now — the class is gone entirely and the bitmap is passed directly, so there is no factory or constructor to choose between.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
##########
pinot-core/src/main/java/org/apache/pinot/core/operator/filter/VectorCandidateScope.java:
##########
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+package org.apache.pinot.core.operator.filter;
+
+import com.google.common.base.Preconditions;
+import org.roaringbitmap.buffer.ImmutableRoaringBitmap;
+
+
+/// Immutable set of document IDs a vector predicate is allowed to consider as candidates.
+///
+/// Vector top-K is not monotonic: unlike an ordinary predicate, restricting the corpus changes which documents win
+/// the top-K contest, so a document set that defines what the query may see must be applied *before* candidate
+/// generation rather than intersected with the result afterwards. That contract is the entire meaning of this type.
+/// It deliberately says nothing about where the restriction came from -- callers such as [FilterPlanNode] decide
+/// that, today from the segment's queryable-document snapshot.
+///
+/// Contrast with the optimizer-selected metadata bitmap passed to
+/// [VectorSimilarityFilterOperator#setPreFilterBitmap]: that one is optional, because post-filtering an ordinary
+/// predicate is already correct and pre-filtering only improves recall.
+///
+/// The factory owns the single detached copy of the supplied bitmap, so operators can share a scope freely and only
+/// allocate again when they intersect it with an independent optional filter.
+public final class VectorCandidateScope {
+ private final ImmutableRoaringBitmap _requiredDocIds;
+
+ private VectorCandidateScope(ImmutableRoaringBitmap requiredDocIds) {
+ // Detach from the caller's bitmap so candidate generation and the outer valid-document AND observe the same
+ // document set for the whole query. Copying into array-backed containers keeps per-document `contains` checks
+ // cheap, which matters because filtered graph traversal probes this bitmap once per visited node.
+ _requiredDocIds = requiredDocIds.toMutableRoaringBitmap().toImmutableRoaringBitmap();
Review Comment:
Removed, along with the copy it was describing.
The comment was trying to justify defensively copying the caller bitmap. That was not worth doing: master already hands the same valid-document snapshot straight to BitmapBasedFilterOperator and iterates it during execution, so copying here bought no safety that the surrounding code does not already assume, and cost an allocation per segment per query. The operator now holds the bitmap by reference with a documented do-not-modify contract, matching that existing convention.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "xiangfu0 (via GitHub)" <gi...@apache.org>.
xiangfu0 merged PR #19297:
URL: https://github.com/apache/pinot/pull/19297
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
Re: [PR] [Vector Upsert 1/5] Support allowed-document filtering in exact vector scan [pinot]
Posted by "codecov-commenter (via GitHub)" <gi...@apache.org>.
codecov-commenter commented on PR #19297:
URL: https://github.com/apache/pinot/pull/19297#issuecomment-5336233281
## [Codecov](https://app.codecov.io/gh/apache/pinot/pull/19297?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
:x: Patch coverage is `0%` with `66 lines` in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 39.21%. Comparing base ([`dfaa2dd`](https://app.codecov.io/gh/apache/pinot/commit/dfaa2dd2af8a51a5a129d1631c9c96126a17cdd9?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)) to head ([`661d325`](https://app.codecov.io/gh/apache/pinot/commit/661d32523f0924919ee81d122c95db9480503e36?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
:warning: Report is 1 commits behind head on master.
| [Files with missing lines](https://app.codecov.io/gh/apache/pinot/pull/19297?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Patch % | Lines |
|---|---|---|
| [...operator/filter/ExactVectorScanFilterOperator.java](https://app.codecov.io/gh/apache/pinot/pull/19297?src=pr&el=tree&filepath=pinot-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fpinot%2Fcore%2Foperator%2Ffilter%2FExactVectorScanFilterOperator.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-cGlub3QtY29yZS9zcmMvbWFpbi9qYXZhL29yZy9hcGFjaGUvcGlub3QvY29yZS9vcGVyYXRvci9maWx0ZXIvRXhhY3RWZWN0b3JTY2FuRmlsdGVyT3BlcmF0b3IuamF2YQ==) | 0.00% | [57 Missing :warning: ](https://app.codecov.io/gh/apache/pinot/pull/19297?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [...not/core/operator/filter/VectorCandidateScope.java](https://app.codecov.io/gh/apache/pinot/pull/19297?src=pr&el=tree&filepath=pinot-core%2Fsrc%2Fmain%2Fjava%2Forg%2Fapache%2Fpinot%2Fcore%2Foperator%2Ffilter%2FVectorCandidateScope.java&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-cGlub3QtY29yZS9zcmMvbWFpbi9qYXZhL29yZy9hcGFjaGUvcGlub3QvY29yZS9vcGVyYXRvci9maWx0ZXIvVmVjdG9yQ2FuZGlkYXRlU2NvcGUuamF2YQ==) | 0.00% | [9 Missing :warning: ](https://app.codecov.io/gh/apache/pinot/pull/19297?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
> :exclamation: There is a different number of reports uploaded between BASE (dfaa2dd) and HEAD (661d325). Click for more details.
>
> <details><summary>HEAD has 24 uploads less than BASE</summary>
>
>| Flag | BASE (dfaa2dd) | HEAD (661d325) |
>|------|------|------|
>|lane-a|2|0|
>|integration|4|0|
>|java-25|6|1|
>|integration1|2|0|
>|temurin|6|1|
>|lane-b|2|0|
>|unittests1|1|0|
>|unittests|2|1|
>|integration2|2|0|
></details>
<details><summary>Additional details and impacted files</summary>
```diff
@@ Coverage Diff @@
## master #19297 +/- ##
=============================================
- Coverage 67.19% 39.21% -27.98%
+ Complexity 1424 1417 -7
=============================================
Files 3462 3463 +1
Lines 220355 220379 +24
Branches 35145 35154 +9
=============================================
- Hits 148059 86418 -61641
- Misses 60498 126085 +65587
+ Partials 11798 7876 -3922
```
| [Flag](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | |
|---|---|---|
| [integration](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [integration1](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [integration2](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [java-25](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `39.21% <0.00%> (-27.98%)` | :arrow_down: |
| [lane-a](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [lane-b](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [temurin](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `39.21% <0.00%> (-27.98%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `39.21% <0.00%> (-27.98%)` | :arrow_down: |
| [unittests1](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [unittests2](https://app.codecov.io/gh/apache/pinot/pull/19297/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `39.21% <0.00%> (+<0.01%)` | :arrow_up: |
Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#carryforward-flags-in-the-pull-request-comment) to find out more.
</details>
[:umbrella: View full report in Codecov by Harness](https://app.codecov.io/gh/apache/pinot/pull/19297?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
<details><summary> :rocket: New features to boost your workflow: </summary>
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org