Tuesday, 19 May 2026

Exploring Vertex and Edge Properties with valueMap in Gremlin

  

When working with graph data, one of the first things you need is visibility, what properties exist on a vertex or an edge, and what values do they hold? Before writing complex traversals, filters, or aggregations, it is essential to understand the structure and content of the data stored in your graph.

 

Apache TinkerPop provides the valueMap step precisely for this purpose. It allows you to inspect the properties of vertices and edges in a structured way, returning them as key–value pairs that are easy to reason about and manipulate in a traversal. In many ways, valueMap plays a role similar to inspecting a row in a relational table but adapted to the flexible, schema-optional nature of graphs.

 

In this post, we will explore how to use valueMap effectively in Gremlin. We will start with the basics retrieving all properties of a vertex and gradually move toward more refined use cases, such as selecting specific properties, including element IDs and labels, improving readability using unfold, and inspecting edge properties.

 

By the end of this article, you will understand:

 

·      How valueMap represents vertex and edge properties

·      Why property values are returned as lists

·      How to include IDs and labels in the output

·      How to limit the result to only the properties you need

·      When and why to use unfold for better readability

·      How valueMap can be used as a powerful debugging and exploration tool

 

Whether you are new to Gremlin or already writing production traversals, mastering valueMap will help you explore your graph faster, write cleaner queries, and avoid unnecessary data retrieval.

 

1. Simple E-Commerce domain

 

Vertex Labels

·      city Bengaluru, Hyderabad, Chennai, Pune

·      category Electronics, Books, Clothing

·      product Laptop, Smartphone, Java Book, T-Shirt

·      customer Amit, Priya, Rohit

·      order O9001 … O9005

 

Edge Labels

·      belongsTo product category

·      placed customer order

·      contains order product

·      deliveredTo order city

 

This models a simple e-commerce order flow:

 

A customer places orders orders contain products products belong to categories orders are delivered to cities.

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()

2. Understanding valueMap in Gremlin

When you work with a graph, every vertex and edge can have properties, small pieces of information stored as key–value pairs. In Gremlin, the valueMap() step is used to retrieve these properties in a structured way.

 

At a high level, valueMap:

 

·      Extracts properties from vertices or edges

·      Returns them as a map of key value

·      Is typically used at the end of a traversal to inspect results

 

Think of valueMap as asking the graph "Show me all (or some) of the properties of the elements I’ve reached".

 

2.1 What does valueMap() return?

A simple call like below return the customerId and name of all the customers.

g.V().
  hasLabel('customer').
  valueMap()

gremlin> g.V().
......1>   hasLabel('customer').
......2>   valueMap()
==>[customerId:[C102],name:[Priya Iyer]]
==>[customerId:[C103],name:[Rohit Verma]]
==>[customerId:[C101],name:[Amit Sharma]]

   

There are two important things to notice here.

·      Properties are returned as lists

·      Even though name and customerId have only one value, Gremlin returns them as lists. 

 

This is because:

·      Vertices in TinkerPop can have multiple values for the same property key

·      valueMap always uses a collection to stay consistent

 

This behavior often surprises beginners, but it’s intentional.

 

2.2 IDs and labels are NOT included by default

By default, valueMap() only returns user-defined properties. It does not include:

 

·      the vertex or edge ID

·      the element label

 

To include them, you must explicitly ask for them by passing true as the first parameter to the valueMap step.

 

g.V().
  hasLabel(customer).
  valueMap(true)

gremlin> g.V().
…...1>   hasLabel(‘customer’).
…...2>   valueMap(true)
[id:33,label:customer,customerId:[C102],name:[Priya Iyer]]
[id:36,label:customer,customerId:[C103],name:[Rohit Verma]]
[id:30,label:customer,customerId:[C101],name:[Amit Sharma]]

   

This is extremely useful when:

·      debugging traversals

·      understanding what kind of element you are looking at

·      learning a new graph schema

 

2.3 Selecting specific properties

You can also tell valueMap exactly which properties you want.

 

g.V().
  hasLabel('customer').
  valueMap('name')

Above snippet select only the customer names.

gremlin> g.V().
......1>   hasLabel('customer').
......2>   valueMap('name')
==>[name:[Priya Iyer]]
==>[name:[Rohit Verma]]
==>[name:[Amit Sharma]]

   

2.4 Select id, label along with name property.

Just pass the first argument as true to select id, label along with name property.

 

g.V().
  hasLabel('customer').
  valueMap(true, 'name')

gremlin> g.V().
......1>   hasLabel('customer').
......2>   valueMap(true, 'name')
==>[id:33,label:customer,name:[Priya Iyer]]
==>[id:36,label:customer,name:[Rohit Verma]]
==>[id:30,label:customer,name:[Amit Sharma]]

3. Using fold and unfold with valueMap

When valueMap() is used in a traversal, it produces a map per element (per vertex or edge). What fold and unfold do is control how those maps are bundled or unbundled as they flow through the traversal.

 

Think in terms of packing and unpacking.

gremlin> g.V().
......1>   hasLabel('customer').
......2>   valueMap()
==>[customerId:[C102],name:[Priya Iyer]]
==>[customerId:[C103],name:[Rohit Verma]]
==>[customerId:[C101],name:[Amit Sharma]]

   

As you see above output, customer details produced as stream of maps.

 

Using unfold() with valueMap

 

gremlin> g.V().
......1>   hasLabel('customer').
......2>   valueMap().
......3>   unfold()
==>customerId=[C102]
==>name=[Priya Iyer]
==>customerId=[C103]
==>name=[Rohit Verma]
==>customerId=[C101]
==>name=[Amit Sharma]

unfold() breaks a collection into individual elements, each entry (key–value pair) is emitted separately

 

Using fold() with valueMap

gremlin> g.V().
......1>   hasLabel('customer').
......2>   valueMap().
......3>   fold()
==>[[customerId:[C102],name:[Priya Iyer]],[customerId:[C103],name:[Rohit Verma]],[customerId:[C101],name:[Amit Sharma]]]

   

fold() does the opposite of unfold(). It collects all incoming elements and packs them into a single list.

 

When should you use fold() with valueMap?

Use fold() when:

·      You want to return a single result

·      You are passing results to an application

·      You want to do post-processing

·      You want to aggregate results

 

4. Using select() with valueMap

The valueMap() step gives you all (or many) properties of an element. But often, you don’t want everything, you only want a few specific fields from the result. That’s where select() comes in.

 

At a high level, select() lets you pick specific keys from a map and discard the rest.

 

Example:

 

g.V().
  hasLabel('customer').
  valueMap().
  select('customerId','name')

   

Above snippet select customerId and name properties.

 

gremlin> g.V().
......1>   hasLabel('customer').
......2>   valueMap().
......3>   select('customerId','name')
==>[customerId:[C102],name:[Priya Iyer]]
==>[customerId:[C103],name:[Rohit Verma]]
==>[customerId:[C101],name:[Amit Sharma]]

 

valueMap('key') vs valueMap().select('key')

·      valueMap('key') limits properties at the source, more efficient and is preferred when you know what you want upfront.

·      valueMap().select('key') filters properties after retrieval

 

In summary, the valueMap step is one of the most practical tools in Gremlin for understanding and exploring graph data. Whether you are learning a new graph model, debugging a traversal, or inspecting results interactively, valueMap gives you clear visibility into the properties stored on vertices and edges. By combining valueMap with steps like unfold, fold, and select, you gain more control over the structure and readability of query results. These steps allow you to move smoothly between exploratory console-friendly output and application-ready result formats.

 

 

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment