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

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

commit 5cc84a043d29fc7f6467c2e2d04067643e7ac3cd
Author: Stephen Mallette <[email protected]>
AuthorDate: Thu Jul 16 12:30:55 2026 -0400

    Document hasLabel() label matching and fix singlelabel docs
    
    hasLabel() tests each label an element carries, so a negation predicate
    retains multi-label vertices that carry the label. Also corrects the
    claim that with("singlelabel") can override a multilabel source, which
    raises a VerificationException instead.
    
    Assisted-by: Claude Code:claude-opus-4-8
---
 docs/src/reference/the-traversal.asciidoc | 45 +++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 14 deletions(-)

diff --git a/docs/src/reference/the-traversal.asciidoc 
b/docs/src/reference/the-traversal.asciidoc
index 104db83ca6..065952a3f3 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -1985,23 +1985,25 @@ gml.V().has('name','tux').valueMap(true)                
     <4>
 <3> A persistent source avoids repeating `with("multilabel")` on each 
traversal.
 <4> `valueMap(true)` also respects the `"multilabel"` configuration.
 
-When a source is configured with `with("multilabel")`, the 
`with("singlelabel")` option can be used per-traversal to
-force single-string label output:
+The companion `with("singlelabel")` option requests the opposite format, 
returning the label as a single string.
+Since the two options call for conflicting output, they are mutually exclusive 
and configuring both on the same
+traversal source raises a `VerificationException`:
 
 [source, groovy]
 ----
-gml = g.with("multilabel")
-gml.V().has('name','marko').elementMap()
 // results in: with("multilabel") and with("singlelabel") are mutually 
exclusive
 //             and cannot both be configured on the same traversal source.
-gml.with("singlelabel").V().has('name','marko').elementMap()
+g.with("multilabel").with("singlelabel").V().has('name','tux').elementMap()
 ----
 
-Since `"multilabel"` and `"singlelabel"` request opposite output formats, 
configuring both on the same traversal
-source is rejected. Attempting to combine them, for example by calling 
`g.with("multilabel").with("singlelabel")`
-will raise a `VerificationException`. The label format is controlled entirely 
by these source options and is independent of the
-graph's `LabelCardinality` setting, so a graph configured for `ZERO_OR_MORE` 
labels will still return a single
-string per element unless `with("multilabel")` is applied.
+Whether a traversal source that specifies neither option produces 
single-string or set-valued labels is a provider
+choice. The reference implementation defaults to a single string, which leaves 
`with("singlelabel")` redundant
+against TinkerGraph. The option exists for providers whose default is 
multi-label output and which need a way to
+request the single-string form.
+
+The label format is controlled entirely by these source options and is 
independent of the graph's `LabelCardinality`
+setting, so a graph configured for `ZERO_OR_MORE` labels will still return a 
single string per element unless
+`with("multilabel")` is applied.
 
 *Additional References*
 
@@ -2363,6 +2365,21 @@ 
g.V().hasLabel('bird').hasLabel('aquatic').values('name')    <2>
 <2> Chaining `hasLabel()` calls requires both labels to be present, matching 
only `tux`, which has both "bird" and
 "aquatic".
 
+More generally, `hasLabel()` applies its test to each label an element carries 
and retains the element when at least
+one label satisfies that test. For elements with a single label the 
distinction never surfaces, but it shapes the
+result of a negation predicate applied to a multi-label vertex:
+
+[gremlin-groovy,theZoo]
+----
+g.V().hasLabel(neq('bird')).values('name')  <1>
+g.V().not(hasLabel('bird')).values('name')  <2>
+----
+
+<1> `tux` carries the "bird" label and is still retained, because its 
remaining labels each satisfy `neq('bird')`.
+This follows from testing a negation against a set of labels rather than a 
single value.
+<2> Wrapping `hasLabel()` in <<not-step,`not()`>> excludes every vertex 
carrying the label, which is the pattern to
+reach for when the intent is to filter such vertices out.
+
 NOTE: When a `Traversal` is provided directly as the value argument (not 
inside a `P`), it is internally wrapped in
 `P.eq(traversal)`. Child traversals must be read-only. Mutating steps like 
`addV()` or `property()` are rejected with
 an `IllegalArgumentException`. See <<a-note-on-predicates,A Note on 
Predicates>> for more details on traversal-bearing
@@ -5728,10 +5745,10 @@ 
g.with("multilabel").V().has('name','tux').valueMap(true)    <2>
 <1> Without `"multilabel"`, the label entry is a single string.
 <2> With `"multilabel"`, all labels are returned as a set.
 
-When a source is configured with `with("multilabel")`, the 
`with("singlelabel")` option can be used per-traversal to
-force single-string label output. Since the two options request opposite 
output formats, configuring both on the
-same traversal source is rejected with a `VerificationException`. As with 
`elementMap()`, the label format is controlled
-entirely by these source options and is independent of the graph's 
`LabelCardinality` setting.
+The companion `with("singlelabel")` option requests labels as a single string 
instead. As with `elementMap()`, the
+two options are mutually exclusive and configuring both on the same traversal 
source raises a `VerificationException`.
+The label format is controlled entirely by these source options and is 
independent of the graph's `LabelCardinality`
+setting. See <<elementmap-step,`elementMap()`>> for a fuller description of 
both options.
 
 *Additional References*
 

Reply via email to