用py2neo对Neo4j进行数据的增删改查:关系
这里接着上一篇的内容,进行关系的创建和关系的查找。
关系的创建和查找
1 创建两个节点间的关系
创建关系时用函数 Relationship() 函数。格式为relation = Relationship(start_node, relationship, end_node) 。start_node为开始节点,end_node为结束节点,relationship 为两节点间的关系。需要知道的是,Neo4j 的关系都是有向的,这里的关系词是由start_node 指向 end_node 的关系。创建后,通过graph.create(relation) 导入Neo4j。
from py2neo import Graph, Node, Relationship from py2neo.matching import * url = 'bolt://localhost:7687' key = '1' usr = 'neo4j' graph = Graph(url, auth = (usr, key)) node_matcher = NodeMatcher(graph) case = node_matcher.match('判决文书', name = 'XXX刑事判决书').first() # 获得name为XXX刑事判决文书的“判决文书”类 节点 people = node_matcher.match('被告人','人', name = 'XXX').first() # 获得name为“XXX”的“被告人”类节点 relation = Relationship(case, '被告人', people) # 创建判决文书和被告人间的关系,关系词为“被告人” graph.create(relation) # 将创建传递到图上
如果创建新的节点和对应的关系怎么办,很简单,先创建节点,再创建关系(注意哦,这个和后续可能的删除顺序是相反的),比如下面示例。我们就不用查询已有节点的,直接将创建的节点用Relationship 连接就好了。但是可能 create 需要逐步来。我自己尝试的时候是不能批量 create 的,如果是需要批量创建节点,建议直接查询 Neo4j 批量创建节点寻找方法,Neo4j 是提供多种批量导入方式的。
2 查找以某种关系直接连接的两个节点
前面在查询节点时,用到的是NodeMatcher。在查询关系时会类似用到RelationshipMatcher,下面直接给出查询两者有直接相连关系的例子。并把我遇到问题进行总结。希望对大家也有所帮助。
首先,来看relation_matcher() 函数的格式。relation_matcher({start-node, end-node}, r_type = XXX, key = value)。这里有三组参数,第一组在 {} 里是起始节点和终止节点,对节点做出限制,可以是None;第二组是关系类型 r_type,第三组是键值组合。这些都可以用在关系查找中,对我们的关系进行限制。在下面例子中,可以看到,relation_matcher() 后面也可以接如.first() 等函数进行补充,比如.where() 用表达式对关系进行限制,用.limit() 限制查找的数量,还有之前出现多次的.exists() 确定是否存在。
接着,来说一说我遇到的问题:
1)能不能查询比较深度的关系,必须直接相连吗,之间隔着一个节点可以吗?我的尝试是不能。如果有朋友尝试出了可以分享一下。
2)在我使用该函数的例子中,如果节点确实存在,确实存在直接的连接关系,是可以正确查询的。
3)使用graph.match() 传同样的参数,是可以替代relation_matcher.match() 的
4)如果我们在 node_matcher.match 部分查找到的其中一个节点结果为空,即这个节点不存在,就会传入空节点。这样会查询另外一个节点(认为这个节点不空)所以与之直接相连符合条件的结果。
from py2neo import Graph, Node, Relationship from py2neo.matching import * url = 'bolt://localhost:7687' key = '1' usr = 'neo4j' graph = Graph(url, auth = (usr, key)) node_matcher = NodeMatcher(graph) # 节点匹配器 relation_matcher = RelationshipMatcher(graph) # 关系匹配器 # 要被查询关系的两个节点,注意,这里不能时自己直接node一个再去匹配的,对于匹配来说,只有连接的graph中存在的节点,才可以被读入。所以我们先要获取一下。内容有重复的节点,不影响 first_node = node_matcher.match('人', name = '张三').first() second_node = node_matcher.match('职业', name = '法外狂徒').first() result = relation_matcher.match({first_node, second_node}, r_type = None, key = value).first() # 查询结果的格式我们是不能直接读的,可以用.first(),或者对结果list,即list(result) print(result) # 打印结果,格式一般是 (节点一)-[关系]->(节点二) print(result.nodes) # 打印节点 graph.separate(relation) # 删除关系 # graph.delete(relation) # 删除关系
3 关系的删除
单独删除关系用函数graph.separate(relationship)。当我们需要删除大图中的一部分节点时,需要先删除关系再删除节点,这时候就会用到这个函数。具体使用在上面的代码中已经实现。separate可以传的参数有关系、节点、图和子图。delete同样