unfold
Feature: (map) expands a list to objects.
Note: The
fold()step is the opposite step, which aggregates objects into a list.
g("thinkerpop").V("1;2;3;4;5;6").hasLabel("person").aggregate("x").by("name").cap("x").unfold()
==> "josh"
==> "marko"
==> "peter"
==> "vadas"
g("thinkerpop").V("1;2;3;4;5;6").hasLabel("person").values("name").fold().unfold()
==> "marko"
==> "josh"
==> "vadas"
==> "peter"unoin
Feature: (branch) merges the results of sub-traversals.
Note: This step provides poor performance because the sub-traversals are serially computed, each with a single step.
g("thinkerpop").V("1;2;3;4;5;6").hasLabel("person").union(outE("knows"),outE("created"))
==> {"label""knows","pk":"1","sk":"4","weight":1.0}
==> {"label""knows","pk":"1","sk":"2","weight":0.5}
==> {"label""created","pk":"1","sk":"3","weight":0.4}
==> {"label""created","pk":"4","sk":"3","weight":0.4}
==> {"label""created","pk":"4","sk":"5","weight":1.0}
==> {"label""created","pk":"6","sk":"3","weight":0.2}until
Feature: (modifier) specifies the condition for terminating a loop traversal.
Note: This step must be used together with the
repeat()step.
V
Feature: (entity) queries information about vertices.
Format: Different primary key strings must be separated with semicolons (
;).Note:
Method for accessing graphs: You can use the
hasLabel()step to specify the graph label of the vertex that you want to access.
g("thinkerpop").V("1;2;3;4;5;6").hasLabel("person")
==> {"label":"person","age":29,"name":"marko","pk":"1"}
==> {"label":"person","age":32,"name":"josh","pk":"4"}
==> {"label":"person","age":27,"name":"vadas","pk":"2"}
==> {"label":"person","age":35,"name":"peter","pk":"6"}values
Feature: (map) returns field values.
Note:
You can use this step to return the values of specific fields. By default, all field values are returned.
You can use the
properties()step to return field names and field values.
g("thinkerpop").V("1;2").hasLabel("person").values()
==> 29
==> "marko"
==> "1"
==> 27
==> "vadas"
==> "2"
g("thinkerpop").V("1;2").hasLabel("person").values("name","age")
==> 29
==> "marko"
==> 27
==> "vadas"where
Feature :(filter) specifies filtering conditions.
Note: You can specify filtering conditions by using the
Pstep.
g("thinkerpop").V("1;2;3;4;5;6").hasLabel("person").values("name").where(is("marko"))
==> "marko"
g("thinkerpop").V("1;2;3;4;5;6").hasLabel("person").where(values("name").is("marko"))
==> {"label""person","age":29,"name":"marko","pk":"1"}
// Query the software that is created by Creator 4 with the co-creator not being Creator 1
// Traverse entities.
g("thinkerpop").E("1").hasLabel("created").inV().aggregate("x").fold().E("4").hasLabel("created").inV().where(P.without("x"))
==> {"label":"software","lang":"java","name":"ripple","pk":"5"}
// The preceding code is equivalent to the following code:
g("thinkerpop").E("1").hasLabel("created").inV().aggregate("x").fold().E("4").hasLabel("created").inV().as("y").where("y",P.without("x"))withSack
Feature: (modifier) defines initial values, split rules, and merge rules for the sack value of an entity.
Syntax:
withSack(initialValueSupplier[,Splitter][,mergeOperator])This step is not completely consistent with the corresponding one in open source Gremlin.
initialValueSupplier: specifies the initial sack value.The following three methods are supported:
kv: separately specifies an initial sack value for each vertex.kkv: separately specifies an initial sack value for each edge.kkv: specifies the same initial sack value for the edges and vertices of an entity.
You can specify multiple sack values for an entity.
An initial sack value is described in the JSON format.
Double quotation marks (" ") in the JSON format must be escaped to prevent parsing conflicts.
In the
kvmethod, the key at the outermost JSON layer corresponds to the primary key of a vertex.In the
kkvmethod, the key at the outermost JSON layer corresponds to the primary key of an edge. The key at the second layer corresponds to the secondary key of the edge.
Splitter: specifies the splitting rule for a sack value. The following three methods are supported:Splitter.identity: suitable for sack values of numeric or string types. This method provides excellent performance.Splitter.fastclone: suitable for sack values of iterator types, including list and map. This method is of excellent performance and low query risk. We recommend that you use this method.If you use this method, the uniqueness of sack values is ensured only under necessary conditions.
Splitter.clone: If the preceding two methods are not suitable, you can use this method. This method is of good performance and no risk.The uniqueness of sack values is ensured.
mergeOperator: specifies the merge rule for sack values that are used in thebarrier()step. The following methods are supported:Operator.sum: adds sack values.Operator.assign: reassigns sack values.Operator.mult: multiplies sack values.Operator.div: divides sack values.Operator.minus: obtains the minimum sack value.Operator.addall: retains all sack values.
Note:
If the
mergeOperatorrule is not specified, the same objects are not merged in thebarrier()step.Precision issues exist in sack values of the floating-point type
__SACK__is used as the built-in keyword that represents the current sack value. You can use the current sack value in expressions for complex computing.sack()is used to return sack values.withSack()is used to return entities and sack values.
// Set the initial sack value to 1.0. If no merge rule is specified, sack values are not merged in the barrier() step. The initial sack value remains unchanged.
g("thinkerpop").withSack(supplier(normal, float,"1.0")).E("1;2;3;4;5;6").hasLabel("created").inV().barrier().sack()
==> 1.0
==> 1.0
==> 1.0
==> 1.0
// Expand the merge result before the result is returned.
g("thinkerpop").withSack(supplier(normal, float,"1.0")).E("1;2;3;4;5;6").hasLabel("created").inV().hasLabel("software").barrier().withSack()
==> {"label""software","lang":"java","name":"lop","pk":"3"},1.0,
==> {"label""software","lang":"java","name":"lop","pk":"3"},1.0,
==> {"label""software","lang":"java","name":"lop","pk":"3"},1.0,
==> {"label""software","lang":"java","name":"ripple","pk":"5"},1.0
// Set the initial sack value to 1.0. Sack values are merged based on the Operator.sum rule.
g("thinkerpop").withSack(supplier(normal, float,"1.0"),Splitter.identity,Operator.sum).E("1;2;3;4;5;6").hasLabel("created").inV().barrier().sack()
==> 3.0
==> 3.0
==> 3.0
==> 1.0
// Expand the merge result before the result is returned.
g("thinkerpop").withSack(supplier(normal, float,"1.0"),Splitter.identity,Operator.sum).E("1;2;3;4;5;6").hasLabel("created").inV().barrier().withSack()
==> {"label""software","lang":"java","name":"lop","pk":"3"},3.0,
==> {"label""software","lang":"java","name":"lop","pk":"3"},3.0,
==> {"label""software","lang":"java","name":"lop","pk":"3"},3.0,
==> {"label""software","lang":"java","name":"ripple","pk":"5"},1.0
// Set the initial sack value to 1.0. When you query an edge with the created label, the sack value is calculated based on the following formula: Sack value = Initial sack value × Weight value.
g("thinkerpop").withSack(supplier(normal, float,"1.0"),Splitter.identity,Operator.sum).E("1;4;6").hasLabel("created").sack(Operator.mult).by("weight").withSack()
==> {"data":[{"label""created","pk":"1","sk":"3","weight":0.4},0.4
==> {"label""created","pk":"4","sk":"3","weight":0.4},0.4
==> {"label""created","pk":"4","sk":"5","weight":1.0},1.0
==> {"label""created","pk":"6","sk":"3","weight":0.2},0.2
// The preceding code is equivalent to the following code:
g("thinkerpop").withSack(supplier(normal, float,"1.0"),Splitter.identity,Operator.sum).E("1;2;3;4;5;6").hasLabel("created").sack(Operator.assign).by("weight*__SACK__").withSack()
// Specify a separate initial sack value for each vertex.
g("thinkerpop").withSack(supplier(kv,"{\"1\":0.3,\"4\":0.7,\"6\":0.4}"),Splitter.identity,Operator.sum).E("1;4;6").hasLabel("created").sack(Operator.mult).by("weight").withSack()
==> {"label""created","pk":"1","sk":"3","weight":0.4},0.12
==> {"label""created","pk":"4","sk":"3","weight":0.4},0.27999999999999999
==> {"label""created","pk":"4","sk":"5","weight":1.0},0.7
==> {"label""created","pk":"6","sk":"3","weight":0.2},0.08000000000000002
// Specify multiple sack values for each vertex, and define different modification rules for each sack value.
g("thinkerpop").withSack(supplier(normal,"{\"k1\":[\"abc\"],\"k2\":1}"),Splitter.fastclone,"{\"k1\":\"Operator.addall\",\"k2\":\"Operator.sum\"}").V("1;2;3;4;5;6").hasLabel("person").sack("k2",Operator.sum).by("to_int(age)").sack("k1",Operator.addall).by(__.values("name").fold()).sack()
==> {"\"k1\"":["abc","marko"],"\"k2\"":30}
==> {"\"k1\"":["abc","josh"],"\"k2\"":33}
==> {"\"k1\"":["abc","vadas"],"\"k2\"":28}
==> {"\"k1\"":["abc","peter"],"\"k2\"":36}withStrategies
Feature: (policy) adds a custom policy for traversal.
Note: The following policies are supported.
This step is not completely consistent with the corresponding one in open source Gremlin.
PathRecordStrategy: supports the custom type of information that is recorded in thepath()step.PushDownStrategy: supports the custom execution position of steps of the sideEffect type