We have already seen the most basic traversal methods: out_e, in_e, both_e, out_v, in_v and both_v. Let's see what else we can do:

Getting properties

We get properties from a route the same way we do for a single element.

properties

Get all properties (of each item in the route). This method returns a route of hash objects.

[]

Get a specific property (of each item in the route). This method returns a route of objects.

Note: Setting properties is done on an individual vertex, not on a route.

limit, offset

# Get at most 99 items
g.v.limit(99)

# Skip the first 3 items
g.v.offset(3)

# Skip the first 5 items, and get the next (at most) 3 items.
g.v.offset(5).limit(3)
# The command above is identical to
g.v.limit(3).offset(5)

The most intuitive use-case of limit and offset is pagination:

page_index     = 0
items_per_page = 100

loop do 
  route = g.v.limit(items_per_page).offset(page_index * items_per_page)
  page_index += 1
  break if route.empty?
end 

range

The range method is an alternative to combining limit and offset:

# Get the range of items from index 10 to 100 (including both).
g.v.range(10, 100)
# The route above is equivalent to
g.v.limit(91).offset(10)

Note: You can also get a range using Ruby's .. range syntax.
For example, g.v[10..100].

uniq

Removes duplicates.

Example:

jruby-1.7.19 :183 > g.v.out_e.in_v
#<V[3]> #<V[0]> #<V[3]> #<V[2]> #<V[2]>
Total: 5

jruby-1.7.19 :184 > g.v.out_e.in_v.uniq
#<V[3]> #<V[0]> #<V[2]>
Total: 3

count

Returns the number of items in the route.

Example:

jruby-1.7.19 :272 > g.v.count
 => 4 

first

Return the first items in a route (or nil, if the route is empty).

Example:

jruby-1.7.19 :272 > g.v.first
 => #<V[0]> 

frequencies

Return a hash, mapping each item to the number of times it occurs in the route.

Example:

jruby-1.7.19 :321 > g.e[:airline]
"Delta"  "Air Canada"  "Delta"  "American Airlines"  "WestJet"          
Total: 5

jruby-1.7.19 :322 > g.e[:airline].frequencies
 => {"Delta"=>2, "Air Canada"=>1, "American Airlines"=>1, "WestJet"=>1} 

paths

When a traversal walks through the graph, Pacer can keep track of what it encounters on each step along the way. You can access that with the Paths Route.

For example, in a graph where vertices are airports and edges are flights, we could ask for all cities we can reach by taking exactly two flight from Toronto:

g.v(city: 'Toronto').out_e.in_v.out_e.in_v[:city]

In my IRB, the output of the above route is:

"Toronto"     "Los Angeles"
Total: 2

If we want to know the full path from New York to each other city, we can use the paths method:

g.v(city: 'New York').out_e.in_v.out_e.in_v.paths

Which, in my IRB, results in the following output:

[#<V[3]>, #<E[6]:3-flight-1>, #<V[1]>, #<E[5]:1-flight-3>, #<V[3]>] 
[#<V[3]>, #<E[6]:3-flight-1>, #<V[1]>, #<E[4]:1-flight-0>, #<V[0]>]
Total: 2

Each of the path above is an array of alternating vertices and edges.
Here is what the paths look like in the sample graph I am currently using in my IRB:

> _.each {|p| puts("#{p[0][:city]} -#{p[1][:airline]}-> #{p[2][:city]} -#{p[3][:airline]}-> #{p[4][:city]}")}

Toronto -Air Canada-> New York -Air Canada-> Toronto
Toronto -Air Canada-> New York -Delta-> Los Angeles

vertices_route?

Return true when called on a vertex or a vertex route.

edges_route?

Return true when called on an edge or an edge route.

Enumerable methods

Routes implement Ruby's Enumerable module. It means that you can use routes like any other Ruby collection, with a few exceptions:

  • Some methods that usually return an array, return a route object.
  • Some methods have extended behaviour.
    For example, map, select and reject are overridden to create steps in a lazy route rather than execute immediately as they would by default.

The table below summarizes these methods.

Method Return a route Has extended behaviour
all?
any?
count
drop X
first
flat_map X X
group_by
include?
last
map X X
reduce
reject X X
select X X
take X
to_a

Convenience methods - in, out and both

Vertices and vertex routes support the following three convenience methods

  • out, get outgoing neighbours of a vertex (or a vertex route).
    This method is (almost) equivalent to out_e.in_v.
  • in, get incoming neighbours of a vertex (or a vertex route).
    This method is (almost) equivalent to in_e.out_v.
  • both, get all neghbours (i.e. the union of out and in).

While useful for exploration in the console, they are often not a good idea in production. They don't preserve information about which edge was followed in the traversal, making it impossible to use certain useful tools like subgraph or the graph export tool rely on that information.

Usage:

  • v.in(:edge_label) only with the given edge label.
  • v.in(:edge_label, :alternate_edge_label) only with one of the given edge labels.
  • v.in(vertex_property: "matching value") only with the exact matching properties.
  • v.in { |vertex| } only when the block returns a truthy value.
  • v.in(Extension) Extend results with the given extension.
  • v.in(:edge_label, Extension, vertex_property: "matching value") { |vertex| } combined