Skip to content

Working with Graph Elements

joeyfreund edited this page Dec 28, 2014 · 4 revisions

Getting elements from the graph

There are a few basic ways to get graph elements from the graph. To get individual elements, you can retrieve them by ID, create new elements against the graph, get the vertex attached to the head or tail of an edge, or pull them out of a collection or stream. To get a stream of elements, you can either start with the stream of all vertices or all edges, use an index, or follow the edges out of a vertex.

Pacer gives you the tools to do all of those things easily and efficiently in addition to allowing you to produce streams of graph elements by building up powerful graph traversals using routes.

Get elements by ID from the graph

All graph databases allow elements to be looked up by ID, though some graphs treat those IDs as implementation details and don't recommend that you expose them to users or store them. That said, getting elements by ID is simple:

vertex = graph.vertex(123)

edge = graph.edge(123)

You can also apply extensions at the same time:

person = graph.vertex(123, Person)

Creating vertices

To create or modify a vertex, depending on the graph you are using you may need to start a transaction.

In the basic case, to create a plain vertex with no properties, the following works:

vertex = graph.create_vertex

You can also specify a custom ID[1], properties and/or extensions or when creating vertices. All of the following are valid combinations:

graph.create_vertex 99
graph.create_vertex Person
graph.create_vertex name: "Wayne Gretzky"
graph.create_vertex 99, Person
graph.create_vertex 99, name: "Wayne Gretzky"
graph.create_vertex Person, name: "Wayne Gretzky"
graph.create_vertex 99, Person, name: "Wayne Gretzky"

Creating edges

An edge must be complete when it is created. That means that you must specify the vertices that it goes from and to, and the edge label. You are still able to optionally specify a custom ID[1] and edge properties:

edge = graph.create_edge nil, player, team, :plays_on_team, season: 2014
edge = graph.create_edge 123, player, team, :plays_on_team, season: 2014

That said, most times you can use Pacer's quick method to create edges, which allows you to quickly create edges between between either single vertices or collections of vertices in a more intuitive way. If any optional properties are specified, they will be applied to each edge created.

Here we create an edge from each player to the team with the season property set, and an edge from the team to each scheduled game in its season:

player_team_edges = players.add_edges_to :plays_on_team, team, season: 2014

team_games_edges = team.add_edges_to :scheduled_game, games

It's also possible to use a collection on both sides of add_edges_to, in which case an edge will be created from each element in the left collection to each element in the right collection:

lots_of_invitation_edges = friends.add_edges_to :invited_to, parties

Using a Vertex

Working with graph element properties

A map of element properties are available via the element.properties method, or you can retrieve just the set of property keys via element.property_keys.

You can get the value of any property with element[:property_name], or set a property value with element[:property_name] = "Value".

Moving from a vertex

There are two basic ways to get at the edges from a vertex. The first and most flexible and powerful way is to start a new route using out_e or in_e - this is the most common. Alternatively, by sacrificing the power of routes, you can also get a very fast, raw iterator of the edges attached to the vertex using out_edges or in_edges - this can be useful inside inner loops or business logic when lookaheads don't work.

Traversing to adjacent elements

You can use out_e, in_e, and both_e to start a traversal from a vertex to a collection of edges. You can also 'jump over' adjacent edges directly to the vertices they are connected to using out, in, and both. All of these methods work exactly the same way as described in Basic routes.

Using edge iterators

Edge iterators are occasionally useful, though most times you want to use the traversal methods above. out_edges, in_edges, and both_edges work the same except for edge direction.

vertex.out_edges(*edge_labels_or_extensions)
vertex.in_edges(*edge_labels_or_extensions)
vertex.both_edges(*edge_labels_or_extensions)

*edge_labels_or_extensions may be substituted with any number of edge labels or extensions. For instance both below examples are valid. The first gets all out edges, the second gets all out edges that have either one of the specified edge labels.

vertex.out_edges
vertex.out_edges(:plays_on_team, :formerly_played_on_team)

Using vertex iterators

You can iterate over directly related vertices in the same way as with edge iterators. With vertex iterators, the optional extensions are applied to the vertex, but you can still specify edge labels in the same way as above:

vertex.out_vertices
vertex.out_vertices(:plays_on_team, :formerly_played_on_team, Person, Player)

Using an Edge

You can work with edge properties in exactly the same way as with vertex properties, except that you can also read the label property on an edge. Every edge has 3 read-only (or immutable) properties: the label, the out_vertex and the in_vertex. You can think of an edge as follows (to borrow Cypher syntax). Both examples below express the same edge.

(out_vertex)-[edge_label]->(in_vertex)

(in_vertex)<-[edge_label]-(out_vertex)

The edge's 2 Vertices

Both out_vertex and in_vertex can wrap the resulting vertex in an extension. Unlike most other such methods, the extension's conditions are not checked before wrapping, so you must take care not to attempt to wrap a vertex retrieved in this way with an incorrect extension.

edge.out_vertex
edge.out_vertex(Person, Player)

Gotchas

Each time you retrieve the same vertex from the graph, a new instance of that vertex will be created. If you are storing transient state on a vertex object, it will not be present on other instances of the object.

Pacer will treat vertices or edges as equal if they have the same ID and come from the same graph. They are not the same reference (identical) if retrieved seperately.

1. When supported. TinkerGraph does support custom IDs, Neo4j does not.