Search code examples
neo4jpy2neo

ObjectModel accessing incoming relations


I have two nodes A and B. They have a directed relation from A to B.

Thus, A has a ConnectedTo attributed of type RelatedTo. However, I want to iterate over all B nodes and access the incoming relations from A.

How can I do this?

I tried adding a ConnectedTo attribute of type RelatedFrom to B but when querying the graph I get a ValueError('Invalid Identifier').

class A(GraphObject):

    __primarykey__ = "hash"

    hash = Property()

    ConnectedTo = RelatedTo('B')

    def __init__(self, hash):
        self.hash = hash


class B(GraphObject):

    __primarykey__ = "hash"

    hash = Property()

    ConnectedTo = RelatedFrom('A')

    def __init__(self, hash):
        self.hash = hash


>>> a = A("testA")
>>> b = B("testB")
>>> a.ConnectedTo.add(b)
>>> graph.push(a)
>>> graph.push(b)
>>> test = B.select(graph).first()

Results in error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/py2neo/ogm.py", line 442, in first
    return self._object_class.wrap(super(GraphObjectSelection, self).first())
  File "/usr/local/lib/python2.7/dist-packages/py2neo/ogm.py", line 344, in wrap
    _ = getattr(inst, attr)
  File "/usr/local/lib/python2.7/dist-packages/py2neo/ogm.py", line 90, in __get__
    related[key] = RelatedObjects(cog.node, self.direction, self.relationship_type, self.related_class)
  File "/usr/local/lib/python2.7/dist-packages/py2neo/ogm.py", line 135, in __init__
    self.__relationship_pattern = "(a)<-[_:%s]-(b)" % cypher_escape(relationship_type)
  File "/usr/local/lib/python2.7/dist-packages/py2neo/database/cypher.py", line 221, in cypher_escape
    writer.write_identifier(identifier)
  File "/usr/local/lib/python2.7/dist-packages/py2neo/database/cypher.py", line 78, in write_identifier
    raise ValueError("Invalid identifier")
ValueError: Invalid identifier

Solution

  • The solution was easier than expected:

    class TestA(GraphObject):
        __primarykey__ = "hash"
        hash = Property()
        CONNECTEDTO = RelatedTo('TestB')
        def __init__(self, hash):
            self.hash = hash
    class TestB(GraphObject):
        __primarykey__ = "hash"
        hash = Property()
        CONNECTEDTO = RelatedFrom('TestA', "CONNECTEDTO")
        def __init__(self, hash):
            self.hash = hash
    
    >>> a = A("testA")
    >>> b = B("testB")
    >>> a.ConnectedTo.add(b)
    >>> graph.push(a)
    >>> graph.push(b)
    >>> test = B.select(graph).first()
    >>> list(test.CONNECTEDTO)
    [ TestA ]
    

    The important part is RelatedFrom('TestA','CONNECTEDTO'). You have to specify what the incoming connection is called.