#python #neo4j #cypher
#python #neo4j #cypher
Вопрос:
Я использую драйвер Neo4j Bolt 1.7 для Python для извлечения путей из определенной базы данных, вот пример кода, который вызывает проблему.
from neo4j import GraphDatabase
uri = "bolt://0.0.0.0:7878"
driver = GraphDatabase.driver(uri, auth=("neo4j", "neo4j"))
db = driver.session()
query = '''
MATCH tree = (n:Class)-[r:SUBCLASSOF*{depth}]->(parent) # <---- ERROR here
WHERE n.obo_id = {go}
RETURN [n in nodes(tree) | n.obo_id] as GOID
'''
results = []
goid = "GO:0051838"
for record in db.run(query, go=goid, depth="..2"):
results.append(record["GOID"])
print(results)
Когда я использую {depth}
параметр, я получаю следующую ошибку:
Traceback (most recent call last):
File "neoEnrich.py", line 16, in <module>
for record in db.run(query, go=goid, depth="..2"):
File "/usr/local/lib/python3.6/site-packages/neo4j/__init__.py", line 499, in run
self._connection.fetch()
File "/usr/local/lib/python3.6/site-packages/neobolt/direct.py", line 414, in fetch
return self._fetch()
File "/usr/local/lib/python3.6/site-packages/neobolt/direct.py", line 454, in _fetch
response.on_failure(summary_metadata or {})
File "/usr/local/lib/python3.6/site-packages/neobolt/direct.py", line 738, in on_failure
raise CypherError.hydrate(**metadata)
neobolt.exceptions.CypherSyntaxError: Parameter maps cannot be used in MATCH patterns (use a literal map instead, eg. "{id: {param}.id}") (line 2, column 38 (offset: 42))
" MATCH tree = (n:Class)-[r:SUBCLASSOF*{depth}]->(parent)"
^
при замене {depth}
на ..2
я получил желаемый результат:
[['GO:0051838', 'GO:0051801'],
['GO:0051838', 'GO:0051801', 'GO:0051883'],
['GO:0051838', 'GO:0051801', 'GO:0051715'],
['GO:0051838', 'GO:0051873'],
['GO:0051838', 'GO:0051873', 'GO:0051883'],
['GO:0051838', 'GO:0051873', 'GO:0051852']]
Есть ли способ разрешить параметры глубины здесь? Поскольку пользователь будет указывать глубину (будет параметром функции).
Ответ №1:
Параметрам не разрешено устанавливать метки узлов, метки отношений, глубины отношений.
Если вам действительно нужна эта глубина в качестве параметра, тогда создайте запрос в виде строки в python и передайте ему глубины отношений в качестве параметра.
Оставьте другие параметры (здесь go
) такими, какие есть в запросе.
Комментарии:
1. Для этого вы можете поискать решение в плагине APOC
Ответ №2:
Вы можете использовать параметры для minLevel
и maxLevel
аргументов функции APOC apoc.path.expand.
Например:
MATCH (n:Class)
WHERE n.obo_id = $go
CALL apoc.path.expand(n, "SUBCLASSOF>", "", 1, $depth) YIELD path
RETURN [n IN NODES(path) | n.obo_id] AS GOID
Ответ №3:
Как насчет
MATCH tree = (n:Class)-[r:SUBCLASSOF*..10]->(parent)
WHERE LENGTH(tree)<=$depth
Ответ №4:
Благодаря @Raj answer самым простым решением, которое я нашел, было использовать .format()
Запрос становится:
query = '''
MATCH tree = (n:Class)-[r:SUBCLASSOF*{depth}]->(parent)
WHERE n.obo_id = "{go}"
RETURN [n in nodes(tree) | n.obo_id] as GOID
'''
Затем сконструировал запрос и выполнил db.run()
full_query = query .format(go=goid, depth="..2")
for record in db.run(full_query):
...