Hello,
I'm stuck for a while on my side project. I want to build a database of exercises. These exercises would be labeled by competencies : as they would be math exercises, competencies would be "fractions", "equations", "functions", etc. Moreover, these competencies are linked and stored in a graph.
I restarted my app from 0, and build a small EducFramework with 3 skills. I want to build the graph on a Web App, so I need to retrieve all the nodes and edges related to this EducFramework.
The request works nice on the Neo4j Browser and I can retrieve the EducFramework with all the nodes and edges.
However, writing the exact same request on Python gives me an empty record, preventing my application to display anything.
The query `MATCH path = (origin:EducFramework {id:$id})-[r*0..]->(x)
WHERE ALL(rel IN relationships(path) WHERE type(rel) IN["comprises","hasSkill"])
RETURN collect(DISTINCT x) as nodes,
[r in collect(distinct last(r))] as rels` returned 1 records in 22 ms.
record: <Record nodes=[] rels=[]>
A simpler MATCH request to retrieve the list of all EducFrameworks will work, but not this one. Did I miss something ?
if you $id is empty ... your output will be empty..
Not sure about your desired output ... but this could be a simpler way as well:
MATCH (origin:EducFramework {id:$id})-[rel:comprises|hasSkill*0..]->(retVal)
RETURN DISTINCT retVal as nodes, [rel in collect(distinct last(rel))] as rels
@joshcornejo, I don't think your return will work as written, as you would need to collect the distinct retVal nodes too.
The refactoring the relationships types is very good. The refactoring can be taken one step further in order to remove the need to de-duplicate the nodes/relationships by getting the single longest path.
MATCH path = (origin:EducFramework {id:$id})-[rel:comprises|hasSkill*0..]->(retVal)
WHERE NOT EXISTS((retVal)-[:comprises|hasSkill]->())
RETURN nodes(path) as nodes, relationships(path) as rels
I agree - I didn't know if the requirement is node, [all relationships for the node]
or just [all nodes], [all relationships]
Thank you for your answers. I used the request from @glilienfield, which is quite simpler than the one I wrote, but the problem remains.
cypher = """MATCH path = (origin:EducFramework {id:$id})-[rel:comprises|hasSkill*0..]->(retVal)
WHERE NOT EXISTS((retVal)-[:comprises|hasSkill]->())
RETURN nodes(path) as nodes, relationships(path) as rels
"""
records, summary, keys = self._driver.execute_query(cypher,
{'id': str(id)},
database_=self.database)
print(f"{len(records)} records for id {id}: {records}")
print("The query `{query}` returned {records_count} records in {time} ms.".format(query=summary.query,
records_count=len(records),
time=summary.result_available_after))
0 records for id e05aab0bf3964b12b5b7c7cc0d9e96a7: []
The query `MATCH path = (origin:EducFramework {id:$id})-[rel:comprises|hasSkill*0..]->(retVal)
WHERE NOT EXISTS((retVal)-[:comprises|hasSkill]->())
RETURN nodes(path) as nodes, relationships(path) as rels
` returned 0 records in 1 ms.
I'm pretty sure there is a problem in my Python code...
Can you executed in desktop to validate the query without the driver/python code?
Do you get anything when looking for only the anchor node?
MATCH (origin:EducFramework {id:”e05aab0bf3964b12b5b7c7cc0d9e96a7”})
Return origin
It is possible your id is uninitialised ... try this python:
cypher = """
MATCH path = (origin:EducFramework {id:$id})-[rel:comprises|hasSkill*0..]->(retVal)
WHERE NOT EXISTS((retVal)-[:comprises|hasSkill]->())
RETURN nodes(path) as nodes, relationships(path) as rels
"""
records, summary, keys = self._driver.execute_query(
cypher,
{'id': str(id)},
database=self.database # Note: no underscore
)
@glilienfield I confirm this query return my node correctly on Neo4j Desktop.
@joshcornejo The id was actually initialised, but I did remove the underscore in the database parameter, and now it works... so much time for a silly "_". Thank you very much ! !
2 Likes