[ 
https://issues.apache.org/jira/browse/TINKERPOP-3261?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18095037#comment-18095037
 ] 

ASF GitHub Bot commented on TINKERPOP-3261:
-------------------------------------------

spmallette commented on code in PR #3483:
URL: https://github.com/apache/tinkerpop/pull/3483#discussion_r3553153086


##########
docs/src/upgrade/release-4.x.x.asciidoc:
##########
@@ -186,6 +186,93 @@ For full details on the interceptor API for each language 
variant, refer to the
 each GLV's documentation in the
 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[Gremlin
 Drivers and Variants]
 reference.
+==== Multi-Label Support
+
+Until now, vertices in the property graph model were limited to a single, 
immutable label assigned at creation. This
+release introduces configurable label cardinality, allowing vertices to carry 
multiple labels that can be added and
+removed over their lifetime.
+
+The feature is controlled by `LabelCardinality`, a graph-level setting that 
defaults to `ONE`, preserving the
+existing single-label behavior. To enable multi-label in TinkerGraph, set the 
vertex label cardinality in the graph
+properties:
+
+```
+gremlin.tinkergraph.vertexLabelCardinality=ZERO_OR_MORE
+```
+
+The three modes are `ONE` (single, immutable, the 3.x default), `ONE_OR_MORE` 
(mutable, minimum one), and
+`ZERO_OR_MORE` (fully flexible). Edge labels remain fixed at `ONE`.
+
+With multi-label enabled, several new traversal steps become available:
+
+```text
+gremlin> g.addV('person','employee').property('name','marko')
+==>v[0]
+gremlin> g.V().has('name','marko').addLabel('manager')
+==>v[0]
+gremlin> g.V().has('name','marko').labels()
+==>person
+==>employee
+==>manager
+gremlin> g.V().has('name','marko').dropLabel('employee').labels()
+==>person
+==>manager
+```
+
+The `labels()` step is a flatMap that emits one traverser per label, unlike 
`label()` which returns a single string.
+For single-label vertices the two behave identically.
+
+The `mergeV()` step accepts a list for `T.label` to match or create 
multi-label vertices. The `onMatch` option uses
+append-only semantics: new labels are added, existing labels are preserved:
+
+```text
+gremlin> g.mergeV([(T.label): ['person','employee'], name: 'marko'])
+==>v[0]
+gremlin> g.mergeV([(T.label): 'person', name: 'marko']).option(Merge.onMatch, 
[(T.label): 'director'])
+==>v[0]
+```
+
+By default, `elementMap()` and `valueMap()` continue to return labels as a 
single string. To receive all labels as a
+set, use `with("multilabel")` either per-traversal or as a persistent source 
configuration:
+
+```text
+// assuming a vertex with labels [person, employee, manager] and name "marko"
+gremlin> g.with("multilabel").V().has('name','marko').elementMap()
+==>{id=0, label=[manager, person, employee], name=marko}
+gremlin> g.V().has('name','marko').elementMap()
+==>{id=0, label=manager, name=marko}
+```
+
+To avoid repeating `with("multilabel")` on every traversal, create a 
persistent source:
+
+```text
+gremlin> gml = g.with("multilabel")
+==>graphtraversalsource[tinkergraph[vertices:1 edges:0], standard]
+gremlin> gml.V().has('name','marko').elementMap()
+==>{id=0, label=[manager, person, employee], name=marko}
+gremlin> gml.V().has('name','marko').valueMap(true)
+==>{id=0, label=[manager, person, employee], name=[marko]}
+```
+
+Note the following behavioral details:
+
+* The deprecated `label()` step returns a single, non-deterministic label when 
multiple labels are present. Always
+  use `labels()` to retrieve the full set reliably.
+* When a source is configured with `with("multilabel")`, the label output can 
be forced back to a single string
+  per-traversal using `with("singlelabel")`. This is useful for providers that 
enable multi-label output by default
+  but need an escape hatch for backward compatibility. Note that when both 
options are present on the same source,
+  `"singlelabel"` always takes precedence regardless of the order in which 
they were applied.
+* Serialization via GraphSON V1/V2/V3 or Gryo only transmits one label per 
vertex (using `label()`). Multi-label data

Review Comment:
   do we have a GraphSON v1/v2/v3 anymore in 4.0? We're running into Gryo 
issues now - is that single label note relevant once we fix that?





> Enable multiple label support on vertex with configurable label cardinality
> ---------------------------------------------------------------------------
>
>                 Key: TINKERPOP-3261
>                 URL: https://issues.apache.org/jira/browse/TINKERPOP-3261
>             Project: TinkerPop
>          Issue Type: Task
>    Affects Versions: 4.0.0
>            Reporter: Yang Xia
>            Priority: Major
>
> Vertices are currently limited to a single immutable label assigned at 
> creation. This prevents modeling common real-world scenarios where entities 
> naturally belong to multiple categories (e.g., a person who is both an 
> employee and a manager).
>   
> Introduce a configurable LabelCardinality that controls how many labels a 
> vertex may have and whether they can be mutated after creation. Three 
> proposed modes: ONE (current behavior, default), ONE_OR_MORE (mutable, 
> minimum one), ZERO_OR_MORE (fully flexible).
>   
> New steps:
>   
> - labels() — flatMap step emitting each label as a traverser
> - addLabel(String, String...) — add labels to a vertex
> - dropLabel(String, String...) — remove specific labels
> - dropLabels() — remove all labels
> Edge labels remain at cardinality ONE. The infrastructure would support 
> future edge multi-label enablement without wire format changes.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to