neomodel
neomodel copied to clipboard
allShortestPaths
Hi!
Thanks for the great package!
I'm trying to get allShortestPaths between two nodes with the following cypher query:
results, _ = db.cypher_query(
"MATCH "
"(from:Point {system_name: 'Point1'}), "
"(to:Point {system_name: 'Point10'}), "
"p = allShortestPaths(from-[:NEXT|CONNECTS_WITH*..100]-to) RETURN p"
)
print([Point.inflate(row[0]) for row in results])
During db.cypher_query
execution the following exception is raised:
Traceback (most recent call last):
File "/usr/local/projects/neo4j/python/lib/python3.4/site-packages/neomodel/util.py", line 195, in cypher_query
results = self._execute_query(query, params)
File "/usr/local/projects/neo4j/python/lib/python3.4/site-packages/neomodel/util.py", line 189, in _execute_query
result = neo4j.CypherResults(cq._cypher._post({'query': query, 'params': params or {}}))
File "/usr/local/projects/neo4j/python/lib/python3.4/site-packages/py2neo/neo4j.py", line 1139, in __init__
for row in content["data"]
File "/usr/local/projects/neo4j/python/lib/python3.4/site-packages/py2neo/neo4j.py", line 1139, in <listcomp>
for row in content["data"]
File "/usr/local/projects/neo4j/python/lib/python3.4/site-packages/neomodel/util.py", line 77, in _hydrated
return type(data)([_hydrated(datum) for datum in data])
File "/usr/local/projects/neo4j/python/lib/python3.4/site-packages/neomodel/util.py", line 77, in <listcomp>
return type(data)([_hydrated(datum) for datum in data])
File "/usr/local/projects/neo4j/python/lib/python3.4/site-packages/neomodel/util.py", line 75, in _hydrated
raise NotImplemented("Don't know how to inflate: " + repr(data))
TypeError: 'NotImplementedType' object is not callable
Am I doing something wrong ?
Hi @maxtepkeev could you provide a very simple test case for this?
I believe I need to add support for paths to neomodel
hi @robinedwards I'm having the same error. Here is a stripped down version of the code which seems to be causing an error. I also have included the errors below, but they are: neo4j-community version 2.1.5 and neomodel 1.0.2
Let me know if you have any suggestions or if I'm just not doing this properly. Thanks
# pymodel example illustrating issues I've been having with getting shortest paths, or all shortest paths.
from neomodel import db
from neomodel import (StructuredNode, StringProperty, IntegerProperty, RelationshipTo, RelationshipFrom)
class Thing(StructuredNode):
text = StringProperty(unique_index=True, required=True)
connection = RelationshipFrom('Thing', 'connects')
def create_nodes():
r = Thing(text="r").save() # should be Node(0)
e = Thing(text="e").save() # should be Node(1)
a = Thing(text="a").save() # should be Node(2)
d = Thing(text="d").save() # should be Node(3)
# let's make the word 'red'
r.connection.connect(e)
e.connection.connect(d)
# let's make the word 'read'
e.connection.connect(a)
a.connection.connect(d)
def raw_cypher(query_string):
return db.cypher_query(query_string)
def nm_cypher(query_string):
results, meta = db.cypher_query(query_string)
return [Thing.inflate(row[0]) for row in results]
def shortestPath(node1, node2):
query_string = "START beginning=node("+str(node1)+"), end=node("+str(node2)+") MATCH p = shortestPath(beginning-[*..500]-end) RETURN p"
raw_cypher(query_string)
"""
Test Commands:
# using neo4j-community version 2.1.5 and neomodel 1.0.2
$ export NEO4J_REST_URL=http://localhost:7474/db/data/
$ python
>> from pymodel_example import *
>> create_nodes()
>> shortestPath(0, 3)
Error:
Traceback (most recent call last):
File "pymodel_example.py", line 46, in <module>
shortestPath(0, 3)
File "pymodel_example.py", line 38, in shortestPath
raw_cypher(query_string)
File "pymodel_example.py", line 28, in raw_cypher
return db.cypher_query(query_string)
File "/Library/Python/2.7/site-packages/neomodel/util.py", line 195, in cypher_query
results = self._execute_query(query, params)
File "/Library/Python/2.7/site-packages/neomodel/util.py", line 189, in _execute_query
result = neo4j.CypherResults(cq._cypher._post({'query': query, 'params': params or {}}))
File "/Library/Python/2.7/site-packages/py2neo/neo4j.py", line 1139, in __init__
for row in content["data"]
File "/Library/Python/2.7/site-packages/neomodel/util.py", line 77, in _hydrated
return type(data)([_hydrated(datum) for datum in data])
File "/Library/Python/2.7/site-packages/neomodel/util.py", line 75, in _hydrated
raise NotImplemented("Don't know how to inflate: " + repr(data))
TypeError: 'NotImplementedType' object is not callable
"""
@maxtepkeev, @richardschwab
This is an interesting feature for a number of reasons but while it is impossible to do exactly what you are after at the moment, writing a response for it made me realise a short and long term improvement we could have in neomodel.
So, the situation is this: Indeed, at the moment we are not resolving the Path
data type which is what the Neo4j driver would return from the database for the sort of queries you indicate there. So:
-
In the short term, you will be able to "unroll" the
Path
'srelationships
with the addition of something likereturn extract(rel in relationships(p)|rel)
. If you perform aneomodel.db.cypher_query
withresolve_objects = True
, this will return a list of your data model's relationship classes which naturally have their start and end nodes at theirstart_node, end_node
attributes. This will be available after finalising this PR.- Also in the short term, I have been in the position where I had to return
allShortestPaths
results and I realised that I did not need all of the data from the path. I was able to return specific properties from the nodes and relationships of the path (again, via acypher_query
) which was enough for my use case.
- Also in the short term, I have been in the position where I had to return
-
In the long term, it will be possible to resolve the
Path
data type. This is not too difficult, but in that case, thePath
could present itself to the user as a starting Node. Anything contained in thePath
would be readily available (because it has travelled from the db to the client) and anything else required would have to be fetched from the dbms with a request (e.g. upon hitting a node, arefresh()
could be performed at will, to ensure that theNode
is fully loaded from the db.).
Hope this helps.
@aanastasiou didn't we recently merge something where we can now resolve Path
objects ? If so, then I think we can close this.
@mariusconjeaud , @maxtepkeev Yes, I just tried this and it should work from 5.1.1 owards.