When working with graph databases using Apache
TinkerPop Gremlin, one of the most common tasks is filtering vertices and edges
based on specific property values. Whether you are analyzing social networks,
transportation networks, or any complex graph structure, the ability to
efficiently test values and ranges is crucial.
Gremlin provides a rich set of predicates that allow
you to compare numbers, strings, or even sets of values. These predicates can
be used in steps like has(), where(), or is(), letting you focus your queries
on just the nodes and edges that matter.
For example, you might want to:
·
Find cities with more than 5 lakes.
·
Identify all routes that avoid certain cities.
·
Query nodes whose IDs fall within a specific range.
·
Filter properties that match a set of allowed or
disallowed values.
These tasks can be handled efficiently with predicates
such as:
|
Predicate
|
Purpose
|
|
eq
|
Equal to a value
|
|
neq
|
Not equal to a value
|
|
gt
|
Greater than
|
|
gte
|
Greater than or equal
|
|
lt
|
Less than
|
|
lte
|
less than or equal
|
|
inside
|
Within bounds (exclusive)
|
|
outside
|
Outside bounds (exclusive)
|
|
between
|
Lower bound inclusive, upper bound exclusive
|
|
within
|
Matches one or more specified values (list or
range)
|
|
without
|
Excludes one or more specified values (list or range)
|
These predicates provide flexibility in querying
graphs, whether you are working with numeric properties (like salaries, age,
discounts etc.,) or strings (like city names or airport codes).
Why Range and Value Testing Matters?
Efficient range and value testing lets you:
·
Filter large graphs quickly: You avoid processing
unnecessary nodes.
·
Perform complex queries: Combine within and without to
include or exclude specific values.
·
Write cleaner queries: Predicates like inside,
outside, or between make your intent explicit.
·
Compare numbers and strings seamlessly: You can handle
both numeric and textual data in your graph without switching approaches.
1. Student Enrollment Graph
Let’s model a school graph where students can enroll
for classes.
Step 1: Create Graph traversal instance.
graph = TinkerGraph.open()
g = graph.traversal()
Step 2: Create Vertices.
// Students
g.addV('student').property('name','Alice').property('age',14).property('grade',9)
g.addV('student').property('name','Bob').property('age',15).property('grade',10)
g.addV('student').property('name','Carol').property('age',13).property('grade',8)
g.addV('student').property('name','David').property('age',14).property('grade',9)
g.addV('student').property('name','Eve').property('age',12).property('grade',7)
// Classes
g.addV('class').property('subject','Math').property('maxStudents',30)
g.addV('class').property('subject','Science').property('maxStudents',25)
g.addV('class').property('subject','History').property('maxStudents',20)
g.addV('class').property('subject','Art').property('maxStudents',15)
Step 3: Connect Students to Classes
// Alice enrolled in Math and Science
g.V().has('student','name','Alice').as('s').
V().has('class','subject','Math').addE('enrolled_in').from('s')
g.V().has('student','name','Alice').as('s').
V().has('class','subject','Science').addE('enrolled_in').from('s')
// Bob enrolled in Math and History
g.V().has('student','name','Bob').as('s').
V().has('class','subject','Math').addE('enrolled_in').from('s')
g.V().has('student','name','Bob').as('s').
V().has('class','subject','History').addE('enrolled_in').from('s')
// Carol enrolled in Science
g.V().has('student','name','Carol').as('s').
V().has('class','subject','Science').addE('enrolled_in').from('s')
// David enrolled in Art and History
g.V().has('student','name','David').as('s').
V().has('class','subject','Art').addE('enrolled_in').from('s')
g.V().has('student','name','David').as('s').
V().has('class','subject','History').addE('enrolled_in').from('s')
// Eve enrolled in Art only
g.V().has('student','name','Eve').as('s').
V().has('class','subject','Art').addE('enrolled_in').from('s')
Let’s print the Graph and confirm the same.
gremlin> g.V().valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:16,label:student,grade:[7],name:[Eve],age:[12]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
==>[id:20,label:class,subject:[Math],maxStudents:[30]]
==>[id:23,label:class,subject:[Science],maxStudents:[25]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:26,label:class,subject:[History],maxStudents:[20]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
==>[id:29,label:class,subject:[Art],maxStudents:[15]]
gremlin>
gremlin> g.E().valueMap(true)
==>[id:32,label:enrolled_in]
==>[id:33,label:enrolled_in]
==>[id:34,label:enrolled_in]
==>[id:35,label:enrolled_in]
==>[id:36,label:enrolled_in]
==>[id:37,label:enrolled_in]
==>[id:38,label:enrolled_in]
==>[id:39,label:enrolled_in]
2. Introducing Predicates
2.1 eq: Equal To
Matches values that are exactly equal.
Example 1: Students who
are exactly 14 years old.
g.V().
hasLabel('student').
has('age', eq(14)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', eq(14)).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
You can even use "has('age', 14)", eq
is optional in simple has() comparisons.
g.V().
hasLabel('student').
has('age', 14).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', 14).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
Example 2: Get all the
students named Alice.
g.V().
hasLabel('student').
has('name', eq('Alice')).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('name', eq('Alice')).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
2.2 neq: Not Equal To
Matches values not equal to the given value.
Example 1: Students not
in grade 9
g.V().
hasLabel('student').
has('grade', neq(9)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('grade', neq(9)).
......3> valueMap(true)
==>[id:16,label:student,grade:[7],name:[Eve],age:[12]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
Example 2: Students not
named Bob
g.V().
hasLabel('student').
has('name', neq('Bob')).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('name', neq('Bob')).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:16,label:student,grade:[7],name:[Eve],age:[12]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
2.3 gt: Greater Than
Example: Students older than 14.
g.V().
hasLabel('student').
has('age', gt(14)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', gt(14)).
......3> valueMap(true)
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
2.4 gte: Greater Than or Equal
Example: Students Greater than or equal
to 14
g.V().
hasLabel('student').
has('age', gte(14)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', gte(14)).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
2.5 lt: Less Than
Example: Students age less than 14.
g.V().
hasLabel('student').
has('age', lt(14)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', lt(14)).
......3> valueMap(true)
==>[id:16,label:student,grade:[7],name:[Eve],age:[12]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
2.6 lte: Less Than or Equal
Example: Students age less than or equal
14.
g.V().
hasLabel('student').
has('age', lte(14)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', lte(14)).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:16,label:student,grade:[7],name:[Eve],age:[12]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
2.7 inside(lower, upper)
Value is strictly between bounds. Both bounds are
excluded (lower < value < upper).
Example: Students aged between 12 and 15
(exclusive).
g.V().
hasLabel('student').
has('age', inside(12, 15)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', inside(12, 15)).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
2.8 outside(lower, upper)
Value is less than lower OR greater than upper, bounds
excluded (value < lower OR value > upper).
Example: Students younger than 13 or
older than 14:
g.V().
hasLabel('student').
has('age', outside(13, 14)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', outside(13, 14)).
......3> valueMap(true)
==>[id:16,label:student,grade:[7],name:[Eve],age:[12]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
2.9 between(lower, upper)
Lower bound inclusive and upper bound exclusive (lower
≤ value < upper).
Example: Students aged 12, 13, or 14:
g.V().
hasLabel('student').
has('age', between(12, 15)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('age', between(12, 15)).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:16,label:student,grade:[7],name:[Eve],age:[12]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
2.10 within(...)
'within' predicate matches any one of the provided
values. It can take:
·
Explicit values
·
A range
·
A list
Example 1: Explicit
values
Students in grades 8, 9, or 10.
g.V().
hasLabel('student').
has('grade', within(8, 9, 10)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('grade', within(8, 9, 10)).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
Example 2: Range syntax
g.V().
hasLabel('student').
has('grade', within(8..10)).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('grade', within(8..10)).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
Example 3: String search
Classes that are Math or Science:
g.V().
hasLabel('class').
has('subject',within('Math','Science')).
valueMap(true)
gremlin> g.V().
......1> hasLabel('class').
......2> has('subject',within('Math','Science')).
......3> valueMap(true)
==>[id:20,label:class,subject:[Math],maxStudents:[30]]
==>[id:23,label:class,subject:[Science],maxStudents:[25]]
Example 4: Using list
notation
g.V().
hasLabel('student').
has('grade', within([8, 9, 10])).
valueMap(true)
gremlin> g.V().
......1> hasLabel('student').
......2> has('grade', within([8, 9, 10])).
......3> valueMap(true)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
==>[id:8,label:student,grade:[8],name:[Carol],age:[13]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
2.11 without(...)
It is just opposite of within, must NOT match any
provided value.
Example 1: Students NOT
in grades 7 or 8.
g.V().
hasLabel('student').
has('grade',without(7,8)).
valueMap().
with(WithOptions.tokens)
gremlin> g.V().
......1> hasLabel('student').
......2> has('grade',without(7,8)).
......3> valueMap().
......4> with(WithOptions.tokens)
==>[id:0,label:student,grade:[9],name:[Alice],age:[14]]
==>[id:4,label:student,grade:[10],name:[Bob],age:[15]]
==>[id:12,label:student,grade:[9],name:[David],age:[14]]
Example 2: Classes that
are NOT Art.
g.V().
hasLabel('class').
has('subject',without('Art')).
valueMap().
with(WithOptions.tokens)
gremlin> g.V().
......1> hasLabel('class').
......2> has('subject',without('Art')).
......3> valueMap().
......4> with(WithOptions.tokens)
==>[id:20,label:class,subject:[Math],maxStudents:[30]]
==>[id:23,label:class,subject:[Science],maxStudents:[25]]
==>[id:26,label:class,subject:[History],maxStudents:[20]]
In summary, understanding value and range testing
predicates is fundamental to writing clean, efficient, and expressive Gremlin
traversals.
In this post, we explored how predicates like:
·
eq, neq: exact matching
·
gt, gte, lt, lte: numeric comparisons
·
inside, outside, between: mathematical range control
·
within, without: multi-value inclusion and exclusion
these predicates allow you to precisely filter
vertices and edges based on property values.
Previous
Next
Home