So far, edge-level traversal has been introduced in two complementary forms:
· outE(): outgoing incident edges
· inE(): incoming incident edges
These steps are ideal when the direction of the relationship matters. However, just as with vertex traversal, there are situations where direction is secondary to connectivity.
Typical questions include:
· What relationships involve this vertex?
· Which edges touch this entity, regardless of direction?
· What events or associations is this node part of?
· These questions are answered using bothE().
Both Incoming and Outgoing Incident Edges
An edge is incident to a vertex if it is connected to that vertex—either as the source or the destination.
For a vertex v:
· Outgoing incident edges: edges where v is the out-vertex
· Incoming incident edges: edges where v is the in-vertex
The bothE() step returns all such edges.
Graphically:
a ---> v ---> b
From the perspective of v:
· The edge from a is incoming
· The edge to b is outgoing
Both edges are incident to v.
Edge Label Filtering
The bothE() step supports filtering by edge labels:
· bothE(): all incident edges
· bothE('contains'): incident edges labeled contains
· bothE('placed', 'deliveredTo'): multiple labels
Label filtering is particularly important in vertices with diverse relationships.
Example: An E-Commerce Graph
To make the discussion concrete, consider an e-commerce domain modeled as a property graph. The graph contains:
Vertex Types
· city: Bengaluru, Hyderabad, Chennai, Pune
· category: Electronics, Books, Clothing
· product: Laptop, Smartphone, Java Programming Book, T-Shirt
· customer: Amit Sharma, Priya Iyer, Rohit Verma
· order: O9001 to O9005
Edge Types
· belongsTo: product → category
· placed: customer → order
· contains: order → product
· deliveredTo: order → city
Each edge has a clear semantic direction that aligns with real-world meaning.
Gremlin Statements to build the Graph
graph = TinkerGraph.open() g = graph.traversal() blr = g.addV('city').property('name', 'Bengaluru').next() hyd = g.addV('city').property('name', 'Hyderabad').next() chn = g.addV('city').property('name', 'Chennai').next() pne = g.addV('city').property('name', 'Pune').next() catElectronics = g.addV('category').property('name', 'Electronics').next() catBooks = g.addV('category').property('name', 'Books').next() catClothing = g.addV('category').property('name', 'Clothing').next() p1 = g.addV('product').property('sku', 'P1001').property('name', 'Laptop').next() p2 = g.addV('product').property('sku', 'P1002').property('name', 'Smartphone').next() p3 = g.addV('product').property('sku', 'P2001').property('name', 'Java Programming Book').next() p4 = g.addV('product').property('sku', 'P3001').property('name', 'T-Shirt').next() g.V(p1).addE('belongsTo').to(catElectronics).next() g.V(p2).addE('belongsTo').to(catElectronics).next() g.V(p3).addE('belongsTo').to(catBooks).next() g.V(p4).addE('belongsTo').to(catClothing).next() c1 = g.addV('customer').property('customerId', 'C101').property('name', 'Amit Sharma').next() c2 = g.addV('customer').property('customerId', 'C102').property('name', 'Priya Iyer').next() c3 = g.addV('customer').property('customerId', 'C103').property('name', 'Rohit Verma').next() o1 = g.addV('order').property('orderId', 'O9001').next() o2 = g.addV('order').property('orderId', 'O9002').next() o3 = g.addV('order').property('orderId', 'O9003').next() o4 = g.addV('order').property('orderId', 'O9004').next() o5 = g.addV('order').property('orderId', 'O9005').next() g.V(c1).addE('placed').to(o1).next() g.V(c1).addE('placed').to(o2).next() g.V(c2).addE('placed').to(o3).next() g.V(c3).addE('placed').to(o4).next() g.V(c3).addE('placed').to(o5).next() g.V(o1).addE('contains').to(p1).next() g.V(o1).addE('contains').to(p3).next() g.V(o2).addE('contains').to(p2).next() g.V(o3).addE('contains').to(p4).next() g.V(o4).addE('contains').to(p1).next() g.V(o4).addE('contains').to(p4).next() g.V(o5).addE('contains').to(p3).next() g.V(o1).addE('deliveredTo').to(blr).next() g.V(o2).addE('deliveredTo').to(blr).next() g.V(o3).addE('deliveredTo').to(hyd).next() g.V(o4).addE('deliveredTo').to(chn).next() g.V(o5).addE('deliveredTo').to(pne).next()
From the established domain model:
· order ──contains──▶ product
· customer ──placed──▶ order
· order ──deliveredTo──▶ city
· product ──belongsTo──▶ category
This implies:
· Products have incoming contains edges
· Orders have incoming placed edges
· Cities have incoming deliveredTo edges
· Categories have incoming belongsTo edges
Example 1: All Relationships Involving an Order
To retrieve every relationship connected to order O9001.
g.V(). has('order', 'orderId', 'O9001'). bothE(). valueMap(true)
gremlin> g.V(). ......1> has('order', 'orderId', 'O9001'). ......2> bothE(). ......3> valueMap(true) ==>[id:54,label:contains] ==>[id:55,label:contains] ==>[id:61,label:deliveredTo] ==>[id:49,label:placed]
Example 2: Combining bothE() with Vertex Steps
To retrieve all vertices connected to an order via any relationship.
g.V(). has('order', 'orderId', 'O9001'). bothE(). bothV(). valueMap(true)
gremlin> g.V(). ......1> has('order', 'orderId', 'O9001'). ......2> bothE(). ......3> bothV(). ......4> valueMap(true) ==>[id:39,label:order,orderId:[O9001]] ==>[id:14,label:product,name:[Laptop],sku:[P1001]] ==>[id:39,label:order,orderId:[O9001]] ==>[id:20,label:product,name:[Java Programming Book],sku:[P2001]] ==>[id:39,label:order,orderId:[O9001]] ==>[id:0,label:city,name:[Bengaluru]] ==>[id:30,label:customer,customerId:[C101],name:[Amit Sharma]] ==>[id:39,label:order,orderId:[O9001]]
As seen in the output, the order with orderId = O9001 appears multiple times. This is expected behavior. The traversal bothE().bothV() means:
“For each relationship connected to this vertex, return both endpoints of that relationship.”
Since the order vertex participates in every incident edge, it is returned once for each such edge, resulting in repeated appearances of the same vertex.
You can use dedup step to remove the duplications.
g.V(). has('order', 'orderId', 'O9001'). bothE(). bothV(). dedup(). valueMap(true)
gremlin> g.V(). ......1> has('order', 'orderId', 'O9001'). ......2> bothE(). ......3> bothV(). ......4> dedup(). ......5> valueMap(true) ==>[id:39,label:order,orderId:[O9001]] ==>[id:14,label:product,name:[Laptop],sku:[P1001]] ==>[id:20,label:product,name:[Java Programming Book],sku:[P2001]] ==>[id:0,label:city,name:[Bengaluru]] ==>[id:30,label:customer,customerId:[C101],name:[Amit Sharma]]
Use otherV() step to exclude the starting vertex.
g.V(). has('order', 'orderId', 'O9001'). bothE(). otherV(). valueMap(true)
gremlin> g.V(). ......1> has('order', 'orderId', 'O9001'). ......2> bothE(). ......3> otherV(). ......4> valueMap(true) ==>[id:14,label:product,name:[Laptop],sku:[P1001]] ==>[id:20,label:product,name:[Java Programming Book],sku:[P2001]] ==>[id:0,label:city,name:[Bengaluru]] ==>[id:30,label:customer,customerId:[C101],name:[Amit Sharma]]
Previous Next Home
No comments:
Post a Comment