-
Notifications
You must be signed in to change notification settings - Fork 30
Working with Graph Elements
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.
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)
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"
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
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"
.
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.
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.
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)
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)
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)
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)
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.