Directionless relationships, first argument the class second the neo4j relationship:

class Person(StructuredNode):
    friends = Relationship('Person', 'FRIEND')

When defining relationships, you may refer to classes in other modules. This avoids cyclic imports:

class Garage(StructuredNode):
    cars = RelationshipTo('transport.models.Car', 'CAR')
    vans = RelationshipTo('.models.Van', 'VAN')


It’s possible to (softly) enforce cardinality restrictions on your relationships. Remember this needs to be declared on both sides of the definition:

class Person(StructuredNode):
    car = RelationshipTo('Car', 'OWNS', cardinality=One)

class Car(StructuredNode):
    owner = RelationshipFrom('Person', 'OWNS', cardinality=One)

The following cardinality classes are available:

ZeroOrOne One
ZeroOrMore (default) OneOrMore

If cardinality is broken by existing data a CardinalityViolation exception is raised. On attempting to break a cardinality restriction a AttemptedCardinalityViolation is raised.


Neomodel uses relationship models to define the properties stored on relations:

class FriendRel(StructuredRel):
    since = DateTimeProperty(
    met = StringProperty()

class Person(StructuredNode):
    name = StringProperty()
    friends = RelationshipTo('Person', 'FRIEND', model=FriendRel)

rel = jim.friends.connect(bob)
rel.since # datetime object

These can be passed in when calling the connect method:

rel = jim.friends.connect(bob,
                          {'since': yesterday, 'met': 'Paris'})

print(rel.start_node().name) # jim
print(rel.end_node().name) # bob

rel.met = "Amsterdam"

You can retrieve relationships between two nodes using the ‘relationship’ method. This is only available for relationships with a defined relationship model:

rel = jim.friends.relationship(bob)

Relationship Uniqueness

By default in neomodel there is only one relationship of one type between two nodes unless you define different properties when calling connect. neomodel utilises CREATE UNIQUE in cypher to achieve this.

Explicit Traversal

It is possible to specify a node traversal by creating a Traversal object. This will get all Person entities that are directly related to another Person, through all relationships:

definition = dict(node_class=Person, direction=OUTGOING,
                  relation_type=None, model=None)
relations_traversal = Traversal(jim, Person.__label__,
all_jims_relations = relations_traversal.all()

The defintion argument is a mapping with these items:

node_class The class of the traversal target node.
direction match.OUTGOING / match.INCOMING / match.EITHER
relation_type Can be None (for any direction), * for all paths or an explicit name of a relation type (the edge’s label).
model The class of the relation model, None for such without one.