-
Notifications
You must be signed in to change notification settings - Fork 276
Neo4j::Rails Relationships
Creating relationships works similar to the Neo4j::NodeMixin
and Neo4j::Node
, except that it is kept in memory before the save method is called.
Example: Let’s say you have two nodes, n1
and n2
. You can create a relationship between those two nodes of type friends of direction outgoing from n2
and incoming from n1
. The relationship will have the type Neo4j::Rails::Relationship
. This done with the following code (could also be done with Neo4j::Rails::Relationship.create
):
n2.incoming(:friends) << n1
n2.save
Notice that the save method will save both the new Neo4j::Rails::Relationship
object and any node that are related to the n2
node (and the same for those nodes !)
The Neo4j::Rails::Model
has the same traversal method as the Neo4j::Node
, see Neo4j::Core-Traverse.
That means that you access nodes with the same method that creates relationship: outgoing
, incoming
and the has_n and has_one accessor methods. All these methods returns an object thats includes the Ruby Enumerable mixin (which means you can use each, collect, find etc).
Example:
m = Member.find(42)
m.outgoing(:posts).find_all{|post| post.keyword == 'ruby'}
# or
m.posts.find_all{|post| post.keyword == 'ruby'}
For more advanced traversals see Neo4j::Core-Traverse
Notice Traversing depth one may contains unpersisted relationship.
The has_one
and has_n
method also generate accessors for getting the relationship objects.
m = Member.find(42)
m.posts_rels.to_a #=> an array of all type Neo4j::Rails::Relationship (or subclass of that).
m.avatar_rel #=> an object of type Neo4j::Rails::Relationship (or subclass of that).
m.avatar_rel.rel_type #=> returns a symbol of the relationship type
You can also access any relationship using the rels and rel method, see Neo4j::Core-Nodes-Properties-Relationships
Validation of relationships and nodes for the friends relationship above will always be performed.
If a related nodes or relationship is not valid then an exception will be raised.
The following example returns all relationships between a and b.
a.rels.to_other(b)
The relationship accessor method also allows you to find the relationships between two nodes using the to_other
method (just like the #rels
method).
To only find the friends relationships between those nodes:
# find all relationships object between p1 and p3, using the has_n accessor
p1.friends_rels.to_other(p3)
# not using the has_n accessor
a.rels(:both, Person.friends).to_other(b)
You can subclass both the Neo4j::Rails::Model and Neo4j::Rails::Relationship classes and specify the relationship between those.
Remember that you can also do this without any declaration at any time (just like for declaring properties or just setting them with the [] operator).
Let say you want to express the domain that an Actor has a Role to a Movie.
Example create three files and put them in the app/model
folder.
app/models/role.rb
class Role < Neo4j::Rails::Relationship
property :title, :character, :index => :exact # index both properties
end
app/models/actor.rb
class Actor < Neo4j::Rails::Model
property :name, :index => :exact
has_n(:acted_in).to(Movie).relationship(Role)
index :name
end
app/models/movie.rb
class Movie < Neo4j::Rails::Model
property :title, :year, :index => :exact
# defines a method for traversing incoming acted_in relationships from Actor
has_n(:actors).from(Actor, :acted_in)
end
Now, when you create a relationship between actor and role it will be of type Role.
Example:
an_actor = Actor.find(42)
an_actor.acted_in << a_film
an_actor.acted_in_rels.first #=> a Role object
# or
role = an_actor.acted_in.create(:title => 'The Matrix')
role.character => 'neo'
role.save
You can now also navigate the incoming direction since we declared has_n(:actors).from(Actor, :acted_in)
matrix.actors.to_a #=> all the actors in that film
Neo4j.rb will prefix relationships when they are declared with to (has_n(:friends).to
).
Example:
actor = Actor.create
actor.acted_in << movie1
actor.outgoing(:acted_in) << movie2
actor.outgoing(:acted_in) # only include movie2
actor.outgoing(Actor.acted_in) # only include movie1
TIP: By not specifying which class the relationship is associated to (using the to
method above) gives you more freedom. If you instead just declared Actor.has_n(:acted_in)
then an actor can have an acted_in relationship to different classes. Example @an_actor.acted_in << Neo4j::Rails::Model.new() << Thingy.create.
As seen in issue #186 and in the code it is, at least by now, a very bad approach to create relationships and link them to nodes after that.
Considering Actor
, Movie
, and Role
objects from above, in Neo4j.rb version 2.0.1 this won’t work:
actor = Actor.first
movie = Movie.first
role = Role.new :title => "A cool film"
role.start_node = actor # raises an "undefined method `start_node='" exception
role.end_node = role # raises an "undefined method `end_node='" exception
Which is the normal behaviour for now because the start_node=
and end_node=
methods are protected
.
WARNING: Much of the information in this wiki is out of date. We are in the process of moving things to readthedocs
- Project Introduction
- Neo4j::ActiveNode
- Neo4j::ActiveRel
- Search and Scope
- Validation, Uniqueness, and Case Sensitivity
- Indexing VS Legacy Indexing
- Optimized Methods
- Inheritance
- Core: Nodes & Rels
- Introduction
- Persistence
- Find : Lucene
- Relationships
- Third Party Gems & extensions
- Scaffolding & Generators
- HA Cluster