contrueCT commented on code in PR #2994:
URL: https://github.com/apache/hugegraph/pull/2994#discussion_r3998493779
##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java:
##########
@@ -602,6 +627,10 @@ private static boolean hasOnlyRangePredicates(HasContainer
has) {
public static void extractHasContainer(HugeVertexStep<?> newStep,
Traversal.Admin<?, ?> traversal) {
+ if (hasUnsafeLabelInTraversal(traversal, newStep)) {
+ prepareLocalHasContainers(newStep, traversal);
Review Comment:
Addressed in 459a2b2f. Added two outgoing-edge paging regressions for the
negative label before and after limit(). Both traverse to cursor exhaustion,
reject duplicate edge IDs and repeated cursors, assert the exact expected IDs,
and explicitly require an empty filtered page with a continuation cursor. On
the SSH test host, all 14 targeted RocksDB edge/vertex paging and
negative-label tests passed with no skips; editorconfig formatting and
full-module clean compile also passed. No optimizer behavior was changed. CI
for the pushed commit is running.
##########
docs/negative-label-queries.md:
##########
@@ -0,0 +1,53 @@
+# Negative-label queries and local filtering
+
+HugeGraph keeps property filters local when pushing them into an index could
+discard vertices or edges needed by a later label predicate. For example,
+`hasLabel(P.neq("author"))` includes other labels even if they do not have the
same
+property indexes. This also applies to unsafe label predicates across barriers,
+ranges and child traversals where the optimizer cannot prove a narrower scope.
+
+## Result completeness changes the no-index behavior
+
+Consider a defined property `unindexedProp` with no property index:
+
+```groovy
+g.V().has("unindexedProp", "x")
+g.V().has("unindexedProp", "x").hasLabel(P.neq("author"))
+```
+
+The first query uses the indexed-property query path and raises
+`NoIndexException`. The second keeps the property predicate local and can scan
+vertices, returning matching non-author vertices. It does **not** use the
+missing-index exception as a fast-fail guard. This is intentional: selecting
+only labels with a matching index could silently omit valid results.
+
+This fallback can turn a selective index lookup into a full candidate scan,
+increasing latency and backend work even when very few results match. Adding an
+index to one label alone does not guarantee that this conservative fallback
will
+use it. When possible, specify a known positive label with a suitable index, or
+start from explicit element IDs. Explicit-ID lookups and adjacent-element
+traversals can filter their own candidates locally; they do not necessarily
scan
+the whole graph.
+
+## Limits and paging
+
+Existing query capacity checks still apply where the execution path enforces
+them. The default capacity is 800,000 records; a candidate scan can reach this
+limit before finding all matching results and raise `LimitExceedException`.
+This is not a universal work bound: the test-only Memory backend does not
enforce
+scan capacity, some count paths disable capacity checks, and a final `limit()`
+bounds returned matches rather than all candidates examined.
+
+With `has("~page", cursor)`, the backend page is bounded before local
filtering.
+A page may contain fewer matches than requested, or no matches at all, while
+still returning a continuation cursor. Continue until the cursor is exhausted;
+do not stop solely because the filtered page is empty. Backends without paging
+support cannot use this mechanism.
+
+## SEARCH predicates
+
+Local `Text.contains()` filters use the graph's SEARCH analyzer and exact term
Review Comment:
Addressed in 459a2b2f. The SEARCH section now limits analyzer-based matching
to the filter chain directly following the source, including barriers, and
states that range/limit/order boundaries stop this adaptation. It includes the
reported post-limit example and explains its literal substring semantics. The
same clarification is included in the PR description and standalone gist; no
SEARCH runtime behavior was changed.
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]