使用 py2neo 到 return 来自 Cypher 查询的节点
Use py2neo to return nodes from Cypher query
我正在尝试使用 py2neo 和 cypher 调用从我的 Neo4j 数据库中对节点进行基本检索,但我找不到 py2neo v4.1 的任何工作代码示例,文档也没有真正的描述、示例、有用信息或教程链接。 SE 上的类似问题使用不再有效的代码。
我有以下密码查询:
getCityNodeQuery= '''MATCH (State) WHERE n.state_name=$sttnm
OPTIONAL MATCH (n:State)<-[:PARTOF]-(county:County) WHERE county.county_name CONTAINS $ctynm
OPTIONAL MATCH (n:State)<-[:PARTOF]-(city:City) WHERE city.city_name CONTAINS $ctynm
OPTIONAL MATCH (n:State)<-[:PARTOF]-(county:County)<-[:PARTOF]-(citycounty:Ward) WHERE citycounty.city_name CONTAINS $ctynm
RETURN county, city, citycounty'''
当我在 Neo4j 桌面浏览器中 运行 为 sttnm
和 ctynm
字段输入值时,我总是得到我正在寻找的东西:单个节点代表该城市(例如输入 "Florida" 和 "Gainesville" 会显示盖恩斯维尔市的节点)。
所以 Cypher 部分本身似乎是正确的,因此问题可能出在我如何从 py2neo 调用它:
def getCityWardNode(prefecture_name, city_name):
thisCityNode = graph.evaluate(getCityNodeQuery, parameters = {'sttnm':state_name, 'ctynm':city_name})
print(thisCityNode)
其中 returns None
.
所以一种想法是我没有正确调用查询,所以它没有返回从 Neo4j 浏览器调用时它所做的节点。但是,当我 运行 只是第一行和 RETURN n
时,我确实得到了正确的 County 节点,所以我对 graph.evaluate()
的使用和我传递参数的方式似乎都是正确的。
我还可以重新安排查询,使县成为匹配城市的条件,这有效并避免了可选匹配。我通过几种方式重新制定了查询,并且以一种方式获得了县,但没有得到县内的城市。不幸的是,我实际上有三个不同的条件可以选择匹配。所以最直接的问题是:
Does py2neo not support OPTIONAL MATCH
within Cypher queries?
所以更一般的问题是:
How do I return the desired node from my Neo4j database using cypher within py2neo?
或
What are the differences between using Cypher queries in Neo4j Browser vs py2neo?
这个问题的解决方案与 py2neo v 4.1.0 中的各种命令 returned 的对象有关。我试图概括 problem/solution 以在我的特定用例之外提供帮助。
运行 neo4j 浏览器中的 Cypher 命令 return 是一个 RECORD
对象和所有节点和边(在浏览器中,即使找到的所有节点之间似乎所有边你没有要求那些边缘)。浏览器将向您显示该记录中的所有项目,而无需您执行任何特殊操作(尽管您可以限制浏览器 returns 使用 LIMIT
作为数字和 WHERE
作为过滤标签和属性)。
Py2neo 有多种选项用于从 Cypher 查询中 returning 对象,none 其中有详细记录,none 其中有有用的示例或对差异的充分解释。但经过多次尝试和失败后,我设法弄清楚了一些事情并让它发挥作用。我将分享我学到的东西,希望其他尝试使用这个包的人不会因为文档不完善而浪费时间。
考虑以下您可以用来从数据库中检索节点的方法。
import py2neo as pn
graph = pn.Graph("bolt://localhost:####/", user="neo4j", password="pwd")
theCypherQuery= '''MATCH (n:Label1) WHERE n.label1_name=$para1
OPTIONAL MATCH (n:Label1)<-[:REL1]-(n2:Label2) WHERE n2.label2_name = $para2
OPTIONAL MATCH (n:Label1)<-[:REL1]-(n3:Label3) WHERE n3.label3_name = $para2
RETURN n2, n3'''
def getNode(thisCypherQuery, parameter1, parameter2):
cypherResult = graph.evaluate(thisCypherQuery, parameters = {'para1':parameter1, 'para2':parameter2})
return cypherResult
someNode = getNode(theCypherQuery,firstParameter,secondParameter)
如果 theCypherQuery
总是 return 正好是一个节点,那么 graph.evaluate
将起作用,因为它实际上 return 是查询生成的记录中的第一个对象。
但是,如果您有一个更复杂的查询 and/or 数据库,可能 return 多个项目(即使只有一个项目是 None
),那么您需要使用 graph.run
而不是 graph.evaluate
。但是 graph.run
return 是一个记录对象,这不是你可以在 Python 中轻松处理的东西,所以有选项:
graph.run(theCypherQuery).data()
returns 结果作为一个字典的列表报告记录中的所有节点 returned。
graph.run(theCypherQuery).table()
return 将字典作为键和值的 table,这似乎最适合打印到控制台。
graph.run(theCypherQuery).evaluate()
相当于上面的 graph.evaluate(theCypherQuery)
并且 return 是第一个对象。
在我的真实案例中,我想在具有不同类型标签的节点之间匹配名称,这些标签是具有特定标签的另一个节点的子节点。我的 Cypher 查询总是 returned 正确的节点,但是有五个 None
对象 returned 以及(对于其他节点标签)它们在浏览器中被简单地忽略但正在破坏我的Python 代码。也许我可以将我的 Cypher 查询更改为仅 return 一个节点,而不管其标签类型如何,但无论如何我认为学习如何处理这些记录对象是个好主意。
这里是一个在Python 中操作returned 记录对象以提取节点并消除None
响应的示例。
def getNode(thisCypherQuery, parameter1, parameter2):
## The returned node is None by default
thisNode = None
## Retrieve the record object from the query, substituting in the parameter values.
## The .data() part returns a list containing a single dictionary.
## So I extract the dictionary by simply pulling item [0].
thisRecord = graph.run(theCypherQuery, parameters = {'para1':parameter1, 'para2':parameter2}).data()[0]
## Now I create a list of non-None values from the dictionary using "list comprehension".
theseNodes = [val for key,val in thisRecord .items() if val != None]
## Perhaps nothing was found, but if at least one item was found...
if len(theseNodes) > 0:
## Then return the first found object (which in my case is the unique matching node)
## Note that this is also necessary to convert the list into a node object.
thisNode = theseNodes[0]
return thisNode
如果您已经精通,那么这里没有什么特别困难的是困难 Python,但是如果没有适当的文档,可能很难理解数据结构以及检索和操作它们的必要条件。在这种情况下,检索到的节点对象与 py2neo 命令兼容,如下所示,根据名称(来自另一个数据源)在两个找到的节点之间创建 link。
firstNode = getNode(theCypherQuery,'UnitedStates','Georgia')
secondNode = getNode(theCypherQuery,'UnitedStates','Jacksonville')
graph.merge(pn.Relationship(firstNode,'BORDERING',secondNode))
请注意,我还没有尝试 return 和操作关系对象,但希望它与获取和使用节点对象没有太大区别。希望您可以修改此代码以检索节点和关系以满足您的需要。
我正在尝试使用 py2neo 和 cypher 调用从我的 Neo4j 数据库中对节点进行基本检索,但我找不到 py2neo v4.1 的任何工作代码示例,文档也没有真正的描述、示例、有用信息或教程链接。 SE 上的类似问题使用不再有效的代码。
我有以下密码查询:
getCityNodeQuery= '''MATCH (State) WHERE n.state_name=$sttnm
OPTIONAL MATCH (n:State)<-[:PARTOF]-(county:County) WHERE county.county_name CONTAINS $ctynm
OPTIONAL MATCH (n:State)<-[:PARTOF]-(city:City) WHERE city.city_name CONTAINS $ctynm
OPTIONAL MATCH (n:State)<-[:PARTOF]-(county:County)<-[:PARTOF]-(citycounty:Ward) WHERE citycounty.city_name CONTAINS $ctynm
RETURN county, city, citycounty'''
当我在 Neo4j 桌面浏览器中 运行 为 sttnm
和 ctynm
字段输入值时,我总是得到我正在寻找的东西:单个节点代表该城市(例如输入 "Florida" 和 "Gainesville" 会显示盖恩斯维尔市的节点)。
所以 Cypher 部分本身似乎是正确的,因此问题可能出在我如何从 py2neo 调用它:
def getCityWardNode(prefecture_name, city_name):
thisCityNode = graph.evaluate(getCityNodeQuery, parameters = {'sttnm':state_name, 'ctynm':city_name})
print(thisCityNode)
其中 returns None
.
所以一种想法是我没有正确调用查询,所以它没有返回从 Neo4j 浏览器调用时它所做的节点。但是,当我 运行 只是第一行和 RETURN n
时,我确实得到了正确的 County 节点,所以我对 graph.evaluate()
的使用和我传递参数的方式似乎都是正确的。
我还可以重新安排查询,使县成为匹配城市的条件,这有效并避免了可选匹配。我通过几种方式重新制定了查询,并且以一种方式获得了县,但没有得到县内的城市。不幸的是,我实际上有三个不同的条件可以选择匹配。所以最直接的问题是:
Does py2neo not support
OPTIONAL MATCH
within Cypher queries?
所以更一般的问题是:
How do I return the desired node from my Neo4j database using cypher within py2neo?
或
What are the differences between using Cypher queries in Neo4j Browser vs py2neo?
这个问题的解决方案与 py2neo v 4.1.0 中的各种命令 returned 的对象有关。我试图概括 problem/solution 以在我的特定用例之外提供帮助。
运行 neo4j 浏览器中的 Cypher 命令 return 是一个 RECORD
对象和所有节点和边(在浏览器中,即使找到的所有节点之间似乎所有边你没有要求那些边缘)。浏览器将向您显示该记录中的所有项目,而无需您执行任何特殊操作(尽管您可以限制浏览器 returns 使用 LIMIT
作为数字和 WHERE
作为过滤标签和属性)。
Py2neo 有多种选项用于从 Cypher 查询中 returning 对象,none 其中有详细记录,none 其中有有用的示例或对差异的充分解释。但经过多次尝试和失败后,我设法弄清楚了一些事情并让它发挥作用。我将分享我学到的东西,希望其他尝试使用这个包的人不会因为文档不完善而浪费时间。
考虑以下您可以用来从数据库中检索节点的方法。
import py2neo as pn
graph = pn.Graph("bolt://localhost:####/", user="neo4j", password="pwd")
theCypherQuery= '''MATCH (n:Label1) WHERE n.label1_name=$para1
OPTIONAL MATCH (n:Label1)<-[:REL1]-(n2:Label2) WHERE n2.label2_name = $para2
OPTIONAL MATCH (n:Label1)<-[:REL1]-(n3:Label3) WHERE n3.label3_name = $para2
RETURN n2, n3'''
def getNode(thisCypherQuery, parameter1, parameter2):
cypherResult = graph.evaluate(thisCypherQuery, parameters = {'para1':parameter1, 'para2':parameter2})
return cypherResult
someNode = getNode(theCypherQuery,firstParameter,secondParameter)
如果 theCypherQuery
总是 return 正好是一个节点,那么 graph.evaluate
将起作用,因为它实际上 return 是查询生成的记录中的第一个对象。
但是,如果您有一个更复杂的查询 and/or 数据库,可能 return 多个项目(即使只有一个项目是 None
),那么您需要使用 graph.run
而不是 graph.evaluate
。但是 graph.run
return 是一个记录对象,这不是你可以在 Python 中轻松处理的东西,所以有选项:
graph.run(theCypherQuery).data()
returns 结果作为一个字典的列表报告记录中的所有节点 returned。graph.run(theCypherQuery).table()
return 将字典作为键和值的 table,这似乎最适合打印到控制台。graph.run(theCypherQuery).evaluate()
相当于上面的graph.evaluate(theCypherQuery)
并且 return 是第一个对象。
在我的真实案例中,我想在具有不同类型标签的节点之间匹配名称,这些标签是具有特定标签的另一个节点的子节点。我的 Cypher 查询总是 returned 正确的节点,但是有五个 None
对象 returned 以及(对于其他节点标签)它们在浏览器中被简单地忽略但正在破坏我的Python 代码。也许我可以将我的 Cypher 查询更改为仅 return 一个节点,而不管其标签类型如何,但无论如何我认为学习如何处理这些记录对象是个好主意。
这里是一个在Python 中操作returned 记录对象以提取节点并消除None
响应的示例。
def getNode(thisCypherQuery, parameter1, parameter2):
## The returned node is None by default
thisNode = None
## Retrieve the record object from the query, substituting in the parameter values.
## The .data() part returns a list containing a single dictionary.
## So I extract the dictionary by simply pulling item [0].
thisRecord = graph.run(theCypherQuery, parameters = {'para1':parameter1, 'para2':parameter2}).data()[0]
## Now I create a list of non-None values from the dictionary using "list comprehension".
theseNodes = [val for key,val in thisRecord .items() if val != None]
## Perhaps nothing was found, but if at least one item was found...
if len(theseNodes) > 0:
## Then return the first found object (which in my case is the unique matching node)
## Note that this is also necessary to convert the list into a node object.
thisNode = theseNodes[0]
return thisNode
如果您已经精通,那么这里没有什么特别困难的是困难 Python,但是如果没有适当的文档,可能很难理解数据结构以及检索和操作它们的必要条件。在这种情况下,检索到的节点对象与 py2neo 命令兼容,如下所示,根据名称(来自另一个数据源)在两个找到的节点之间创建 link。
firstNode = getNode(theCypherQuery,'UnitedStates','Georgia')
secondNode = getNode(theCypherQuery,'UnitedStates','Jacksonville')
graph.merge(pn.Relationship(firstNode,'BORDERING',secondNode))
请注意,我还没有尝试 return 和操作关系对象,但希望它与获取和使用节点对象没有太大区别。希望您可以修改此代码以检索节点和关系以满足您的需要。