1. Adjacency and Incidence in Property Graphs
In a property graph, relationships are first class citizens. Understanding how vertices and edges relate to one another is fundamental before exploring traversal steps such as out().
Vertex Adjacency
Two vertices are said to be adjacent if there is an edge connecting them.
· If vertex A is connected to vertex B by an edge, then A and B are adjacent.
· Adjacency does not imply direction by itself; direction becomes relevant only when the edge is directed.
For example, if an order vertex is connected to a product vertex via a contains edge, those two vertices are adjacent.
Vertex Edge Incidence
A vertex and an edge are considered incident if the edge is connected to that vertex.
· An edge is incident to its out-vertex and its in-vertex.
· This concept becomes important when reasoning about traversal direction and edge filtering.
Think of incidence as participation, a vertex participates in an edge if the edge starts from or ends at that vertex.
Direction Matters: Incoming and Outgoing Relationships
Apache TinkerPop follows the directed property graph model. Every edge has a direction:
· Outgoing direction: from the out-vertex to the in-vertex
· Incoming direction: from the in-vertex back to the out-vertex
Gremlin provides explicit steps to navigate these directions:
· out() – move to outgoing adjacent vertices
· in() – move to incoming adjacent vertices
· both() – move to all adjacent vertices regardless of direction
This chapter focuses on out().
What out() Does?
The out() step traverses from a vertex to all vertices connected by outgoing edges.
In precise terms:
· Starting from a vertex V
· Follow all edges where V is the out-vertex
· Emit the connected in-vertices
V --(edge)--> adjacent vertex
Only edges leaving the current vertex are considered.
Filtering by Edge Label
The out() step can optionally take one or more edge labels.
· out(): follow all outgoing edges
· out('placed'): follow only outgoing edges with the label placed
This makes out() both a navigation and filtering step.
2. 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()
Example 1: Print all vertices and edges
gremlin> g.V().valueMap(true) ==>[id:0,label:city,name:[Bengaluru]] ==>[id:33,label:customer,customerId:[C102],name:[Priya Iyer]] ==>[id:2,label:city,name:[Hyderabad]] ==>[id:4,label:city,name:[Chennai]] ==>[id:36,label:customer,customerId:[C103],name:[Rohit Verma]] ==>[id:6,label:city,name:[Pune]] ==>[id:39,label:order,orderId:[O9001]] ==>[id:8,label:category,name:[Electronics]] ==>[id:41,label:order,orderId:[O9002]] ==>[id:10,label:category,name:[Books]] ==>[id:43,label:order,orderId:[O9003]] ==>[id:12,label:category,name:[Clothing]] ==>[id:45,label:order,orderId:[O9004]] ==>[id:14,label:product,name:[Laptop],sku:[P1001]] ==>[id:47,label:order,orderId:[O9005]] ==>[id:17,label:product,name:[Smartphone],sku:[P1002]] ==>[id:20,label:product,name:[Java Programming Book],sku:[P2001]] ==>[id:23,label:product,name:[T-Shirt],sku:[P3001]] ==>[id:30,label:customer,customerId:[C101],name:[Amit Sharma]] gremlin> gremlin> gremlin> gremlin> g.E().valueMap(true) ==>[id:64,label:deliveredTo] ==>[id:65,label:deliveredTo] ==>[id:49,label:placed] ==>[id:50,label:placed] ==>[id:51,label:placed] ==>[id:52,label:placed] ==>[id:53,label:placed] ==>[id:54,label:contains] ==>[id:55,label:contains] ==>[id:56,label:contains] ==>[id:57,label:contains] ==>[id:26,label:belongsTo] ==>[id:58,label:contains] ==>[id:27,label:belongsTo] ==>[id:59,label:contains] ==>[id:28,label:belongsTo] ==>[id:60,label:contains] ==>[id:29,label:belongsTo] ==>[id:61,label:deliveredTo] ==>[id:62,label:deliveredTo] ==>[id:63,label:deliveredTo]
Example 2: Get all the orders placed by a customer.
g.V(). has('customer', 'name', 'Amit Sharma'). out('placed'). valueMap(true)
gremlin> g.V(). ......1> has('customer', 'name', 'Amit Sharma'). ......2> out('placed'). ......3> valueMap(true) ==>[id:39,label:order,orderId:[O9001]] ==>[id:41,label:order,orderId:[O9002]]
Example 3: Products Contained in an Order
g.V(). has('order', 'orderId', 'O9001'). out('contains'). valueMap(true)
gremlin> g.V(). ......1> has('order', 'orderId', 'O9001'). ......2> out('contains'). ......3> valueMap(true) ==>[id:14,label:product,name:[Laptop],sku:[P1001]] ==>[id:20,label:product,name:[Java Programming Book],sku:[P2001]]
Example 4: Get me the city where the order id delivered to
g.V(). has('order', 'orderId', 'O9001'). out('deliveredTo'). valueMap(true)
gremlin> g.V(). ......1> has('order', 'orderId', 'O9001'). ......2> out('deliveredTo'). ......3> valueMap(true) ==>[id:0,label:city,name:[Bengaluru]]
In well-modeled graphs, most business questions read left to right using out():
· Customers → orders → products
· Orders → delivery locations
· Products → categories
This clarity is a direct result of choosing correct edge directions during modeling.
In summary:
· Adjacency describes vertices connected by an edge
· Incidence describes the relationship between a vertex and an edge
· out() traverses to outgoing adjacent vertices only
· Edge direction is not optional—it defines traversal semantics
· Clear edge naming and direction make out() traversals intuitive and readable
Previous Next Home
No comments:
Post a Comment