Suppose I have the following models from the neomodel documentation.
class FriendRel(StructuredRel):
since = DateTimeProperty(
default=lambda: datetime.now(pytz.utc)
)
met = StringProperty()
class Person(StructuredNode):
name = StringProperty()
friends = RelationshipTo('Person', 'FRIEND', model=FriendRel)
And I create the following data.
bob = Person(name='bob').save()
frank = Person(name='frank').save()
rel = bob.friends.connect(frank, {'since': dt.datetime.now(), 'met': 'Germany'})
Now my question is how I should go about retrieving both the friends of an object and the corresponding FriendshipRel objects between those relationships.
The Neomodel docs seem to say to do the following.
>>> bob = Person.nodes.get(name='bob')
>>> frank = bob.friends[0] # get bob's friend frank using database query?
>>> rel = bob.friends.relationship(frank) # query database again?
>>> rel.met
'Germany'
When doing this, it really feels like there would be a better way of retrieving relationship objects without another database query. I would expect these relationship objects to already be cached when you retrieve a node's friends?
So in a loop, would this be the best way to retrieve all of a Person's friends and the FriendshipRel objects for those friendships?
# source: https://stackoverflow.com/questions/67821341/retrieve-the-relationship-object-in-neomodel
for friend in bob.friends:
rel = bob.friends.relationship(friend)
This seems quite inefficient, as doesn't it require another database query for each relationship? Or am I not understanding correctly?
With cypher, I would just do the following:
MATCH(i:Person{name: 'bob'})-[j:FRIEND]->(k) RETURN i,j,k
So my question: is there a way, using neomodel, to retrieve a node's relationships and the objects for those relationships both at the same time?
I've checked the neomodel source code and there doesn't seem to be a way to achieve what I want in a more efficient way than what I found in this stackoverflow answer.
But I now know how to do this using cypher queries like so:
from neomodel import db
from models import Person, FriendRel
bob = Person.nodes.get(name='bob')
# Only one database query. Yay!
results, cols = db.cypher_query(f"""MATCH (node)-[rel]-(neighbor)
WHERE id(node)={john.id}
RETURN node, rel, neighbor""")
rels = {} # friendships mapped to neighbor node ids
neighbors = []
for row in results:
neighbor = Person.inflate(row[cols.index('neighbor')])
neighbors.append(neighbor)
rel = FriendRel.inflate(row[cols.index('rel')])
rels[neighbor.id] = rel
Then, now that you've stored all neighbors and the relationships between them, you can loop through them like so:
for neighbor, rel in rels:
print(f"bob has a friendship with {neighbor}.")
print(f"They've been friends since {rel.since}")
Or like so:
for neighbor in neighbors:
rel = rels[neighbor.id]
Thanks to everyone's helpful advice!