-
Notifications
You must be signed in to change notification settings - Fork 862
[TINKERPOP-3261] Enable multiple labels on vertex with configurable label cardinality #3483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 17 commits
da4ec2a
be3e714
f4180a2
be5072e
6a3c91e
99f496a
687878f
dfc1827
561723f
d6c57e2
1310986
f1e678b
102938e
b88f22e
43e0336
9ea3df1
2958a30
278b64b
d272791
0b33a8f
2eefc22
083c9a6
9db5db5
7855ccf
db79ef9
d036429
941dd3e
3e761ce
e5f35a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -587,6 +587,84 @@ See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/j | |
| link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java[source (start)], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#addvertex-step[reference] | ||
|
|
||
| === addLabel() | ||
|
|
||
| *Description:* Adds one or more labels to an element. | ||
|
|
||
| *Syntax:* `addLabel(String label, String... moreLabels)` | `addLabel(Traversal<?, ?> labelTraversal, Traversal<?, ?>... moreLabelTraversals)` | ||
|
|
||
| [width="100%",options="header"] | ||
| |========================================================= | ||
| |Start Step |Mid Step |Modulated |Domain |Range | ||
| |N |Y |N |`Element` |`Element` | ||
| |========================================================= | ||
|
|
||
| *Arguments:* | ||
|
|
||
| * `label` - The label to add. | ||
| * `moreLabels` - Additional labels to add. | ||
| * `labelTraversal` - The first (or only) traversal that produces a label to add. | ||
| * `moreLabelTraversals` - Additional label-producing traversals (may be empty for single-traversal behavior). | ||
|
|
||
| *Considerations:* | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
"supports mutation"? First, that sounds a bit odd...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've reworded this for clarity, but yes singlelabel does imply immutability, because there is no atomic operation to replace labels, and there labels cannot be added or removed without violating the cardinality. This also keeps |
||
|
|
||
| Label add and remove operations require a `LabelCardinality` that permits changing the set of labels on an element | ||
| (`ONE_OR_MORE` or `ZERO_OR_MORE`). When `LabelCardinality` is `ONE`, the vertex's label is fixed at creation and | ||
| cannot be added to or removed. | ||
| Adding a label that already exists on the element is a no-op. The step returns the element (sideEffect semantics). | ||
| Each traversal argument is iterated for a single result only. If exactly one traversal is provided and it produces | ||
| a `Collection<String>`, the collection will be automatically unfolded into the set of labels added; if more than one | ||
| traversal is provided, each must resolve to a single `String` label. | ||
|
|
||
| *Exceptions* | ||
|
|
||
| * If the graph's `LabelCardinality` does not permit label modification, an `IllegalStateException` will be thrown. | ||
| * If any label argument is null or empty, an `IllegalArgumentException` will be thrown. | ||
| * If more than one traversal is provided and any of them produces a `Collection`, an `IllegalArgumentException` will | ||
| be thrown. | ||
|
|
||
| See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddLabelStep.java[source], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#addlabel-step[reference] | ||
|
|
||
| === dropLabel() | ||
|
|
||
| *Description:* Removes one or more specific labels from an element, or removes all labels. | ||
|
|
||
| *Syntax:* `dropLabel(String label, String... moreLabels)` | `dropLabel(Traversal<?, String> labelTraversal, Traversal<?, String>... moreLabelTraversals)` | `dropLabels()` | ||
|
|
||
| [width="100%",options="header"] | ||
| |========================================================= | ||
| |Start Step |Mid Step |Modulated |Domain |Range | ||
| |N |Y |N |`Element` |`Element` | ||
| |========================================================= | ||
|
|
||
| *Arguments:* | ||
|
|
||
| * `label` - The label to remove. | ||
| * `moreLabels` - Additional labels to remove. | ||
| * `labelTraversal` - The first (or only) traversal that produces a label to remove. | ||
| * `moreLabelTraversals` - Additional label-producing traversals (may be empty for single-traversal behavior). | ||
|
|
||
| *Considerations:* | ||
|
|
||
| Label add and remove operations require a `LabelCardinality` that permits changing the set of labels on an element | ||
| (`ONE_OR_MORE` or `ZERO_OR_MORE`). Dropping a label that does not exist | ||
| on the element is a no-op. `dropLabels()` removes all labels (only valid with `ZERO_OR_MORE`). The step returns the | ||
| element (sideEffect semantics). | ||
| Each traversal argument is iterated for a single result only. If exactly one traversal is provided and it produces | ||
| a `Collection<String>`, the collection will be automatically unfolded into the set of labels removed; if more than | ||
| one traversal is provided, each must resolve to a single `String` label. | ||
|
|
||
| *Exceptions* | ||
|
|
||
| * If the graph's `LabelCardinality` does not permit label modification, an `IllegalStateException` will be thrown. | ||
| * If `dropLabel()` or `dropLabels()` would violate the minimum label count, an `IllegalStateException` will be thrown. | ||
| * If more than one traversal is provided and any of them produces a `Collection`, an `IllegalArgumentException` will | ||
| be thrown. | ||
|
|
||
| See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/DropLabelsStep.java[source], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#droplabel-step[reference] | ||
|
|
||
| [[all-step]] | ||
| === all() | ||
|
|
||
|
|
@@ -1637,6 +1715,52 @@ See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/j | |
| link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java[source (sideEffect)], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#groupcount-step[reference] | ||
|
|
||
| [[label-step]] | ||
| === label() | ||
|
|
||
| *Description:* Maps an element to its label as a single string value. | ||
|
|
||
| *Syntax:* `label()` | ||
|
|
||
| [width="100%",options="header"] | ||
| |========================================================= | ||
| |Start Step |Mid Step |Modulated |Domain |Range | ||
| |N |Y |N |`Element` |`String` | ||
| |========================================================= | ||
|
|
||
| *Considerations:* | ||
|
|
||
| The `label()` step returns exactly one label string per element. For graphs that support multiple labels per vertex, | ||
| `label()` returns only one of the vertex's labels and the choice is non-deterministic (implementation-dependent | ||
| ordering). Use `labels()` to retrieve all labels reliably. | ||
|
|
||
| See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelStep.java[source], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#label-step[reference] | ||
|
|
||
| [[labels-step]] | ||
| === labels() | ||
|
Cole-Greer marked this conversation as resolved.
|
||
|
|
||
| *Description:* Maps an element to its labels, emitting one traverser per label. | ||
|
|
||
| *Syntax:* `labels()` | ||
|
|
||
| [width="100%",options="header"] | ||
| |========================================================= | ||
| |Start Step |Mid Step |Modulated |Domain |Range | ||
| |N |Y |N |`Element` |`String` | ||
| |========================================================= | ||
|
|
||
| *Considerations:* | ||
|
|
||
| For vertices with a single label, `labels()` emits one traverser (equivalent to `label()`). For multi-label vertices, | ||
| it emits one traverser per label. For vertices with zero labels (`ZERO_OR_MORE` mode), no traversers are emitted. | ||
|
|
||
| `hasLabel("a", "b")` uses OR semantics: it matches any vertex that has label "a" or label "b". To match vertices | ||
|
Cole-Greer marked this conversation as resolved.
Outdated
|
||
| with all specified labels, chain calls: `hasLabel("a").hasLabel("b")`. | ||
|
|
||
| See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelsStep.java[source], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#labels-step[reference] | ||
|
|
||
| [[length-step]] | ||
| === length() | ||
|
|
||
|
|
@@ -2564,6 +2688,13 @@ the possible values are: | |
| ** 8 for including values (VertexProperty) | ||
| ** 15 for including all | ||
|
|
||
| The label format in the map is controlled by source-level `with("multilabel")` and `with("singlelabel")` options, not | ||
| by the graph's `LabelCardinality`. When `"multilabel"` is present and `"singlelabel"` is not, the label value is a | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
that's an odd way to say that, no? it's not like they make any sense both being configured. ah, but then:
I'm not sure I like that. I suppose it's better than an error? Was this an explicit design choice? |
||
| `Set<String>`; otherwise it is a single `String`. As a deliberate design choice, when both options are present on the | ||
| same source, `"singlelabel"` always takes precedence regardless of the order in which they were applied. This ensures | ||
| deterministic behavior rather than relying on declaration order. Providers who want label output tied to their | ||
| cardinality configuration should override `PropertyMapStep` and/or `ElementMapStep`. | ||
|
Cole-Greer marked this conversation as resolved.
Outdated
|
||
|
|
||
| See: link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java[source], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#valuemap-step[reference], | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/reference/#propertymap-step[reference] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -166,6 +166,7 @@ TinkerGraph has several settings that can be provided on creation via `Configura | |
| |gremlin.tinkergraph.vertexPropertyIdManager |The `IdManager` implementation to use for vertex properties. | ||
| |gremlin.tinkergraph.defaultVertexPropertyCardinality |The default `VertexProperty.Cardinality` to use when `Vertex.property(k,v)` is called. | ||
| |gremlin.tinkergraph.allowNullPropertyValues |A boolean value that determines whether or not `null` property values are allowed and defaults to `false`. | ||
| |gremlin.tinkergraph.vertexLabelCardinality |The `LabelCardinality` for vertices. Options are `ONE` (default, single immutable label, backward-compatible with 3.x), `ONE_OR_MORE` (at least one label, mutable), or `ZERO_OR_MORE` (zero or more labels). See <<tinkergraph-multi-label>>. | ||
| |gremlin.tinkergraph.graphLocation |The path and file name for where TinkerGraph should persist the graph data. If a | ||
| value is specified here, the `gremlin.tinkergraph.graphFormat` should also be specified. If this value is not | ||
| included (default), then the graph will stay in-memory and not be loaded/persisted to disk. | ||
|
|
@@ -219,6 +220,35 @@ g.io("data/tinkerpop-crew.kryo").read().iterate() | |
| g.V().properties() | ||
| ---- | ||
|
|
||
| [[tinkergraph-multi-label]] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're missing a lot of docs updates. TinkerGraph isn't the story here. The story is that TinkerPop now has multi-label support. The entire reference guide, recipes, tutorials, etc. need review. At minimum, we have to conceptually introduce this change to the "structure" at the front end of the reference docs: https://tinkerpop.apache.org/docs/current/reference/#graph-structure We should be looking to explain this feature throughout the docs in a seamless fashion. |
||
| === Multi-Label Support | ||
|
|
||
| TinkerGraph supports multiple labels per vertex when `gremlin.tinkergraph.vertexLabelCardinality` is set to | ||
| `ONE_OR_MORE` or `ZERO_OR_MORE`. This enables use of the `addLabel()`, `dropLabel()`, `dropLabels()`, and `labels()` | ||
| traversal steps. | ||
|
|
||
| [gremlin-groovy] | ||
| ---- | ||
| conf = new BaseConfiguration() | ||
| conf.setProperty("gremlin.tinkergraph.vertexLabelCardinality", "ZERO_OR_MORE") | ||
| graph = TinkerGraph.open(conf) | ||
| g = traversal().with(graph) | ||
| g.addV("person","employee").property("name","marko").iterate() | ||
| g.V().has("name","marko").labels() <1> | ||
| g.V().has("name","marko").addLabel("manager").labels() <2> | ||
| g.V().has("name","marko").dropLabel("employee").labels() <3> | ||
| ---- | ||
|
|
||
| <1> The vertex was created with two labels. | ||
| <2> A third label is added. | ||
| <3> One label is removed. | ||
|
|
||
| The `hasLabel()` step works with multi-label vertices using OR semantics: `hasLabel("a","b")` matches any vertex that | ||
| has label "a" OR label "b". To match vertices having both labels, chain multiple `hasLabel()` calls: | ||
| `hasLabel("a").hasLabel("b")`. | ||
|
|
||
| IMPORTANT: Edges always have exactly one label — multi-label support applies to vertices only. | ||
|
|
||
| [[tinkergraph-gremlin-tx]] | ||
| === Transactions | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -179,6 +179,17 @@ g.V().has('name','gremlin').inE('uses'). | |
| select('a','b').by('skill').by('name') // rank the users of gremlin by their skill level | ||
| ---- | ||
|
|
||
| [[vertex-labels]] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that since we make this introduction here, it would be good to describe use cases. This just tells the reader they can do it maybe but doesn't explain much about what it would be used for and when you should and shouldn't reach for it.. |
||
| === Vertex Labels | ||
|
|
||
| In addition to multi-properties and meta-properties, TinkerPop supports multiple labels on a single vertex. The number | ||
| of labels a vertex may carry is governed by the graph's configured `LabelCardinality`: `ONE` fixes exactly one immutable | ||
| label per vertex (the traditional model), `ONE_OR_MORE` requires at least one label but permits additional labels to be | ||
| added or removed, and `ZERO_OR_MORE` allows a vertex to have any number of labels including none. See the | ||
| link:https://tinkerpop.apache.org/docs/x.y.z/dev/provider/#_label_cardinality[provider documentation] for configuration | ||
| details and the <<label-step,label()>>, <<labels-step,labels()>>, <<addlabel-step,addLabel()>>, and | ||
| <<droplabel-step,dropLabel()>> steps for traversal access. | ||
|
|
||
| == Graph Variables | ||
|
|
||
| `Graph.Variables` are key/value pairs associated with the graph itself -- in essence, a `Map<String,Object>`. These | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.