关于py2neo中的merge,create,当反复执行时,会出现什么。。。

关于py2neo中的merge,create,当反复执行时,会出现什么。。。,第1张

先导包和创建点和关系

先把包导了,把Log也打印出来:

from py2neo import Node, Relationship, Graph, NodeMatcher,Subgraph
import logging
logging.basicConfig(level=logging.DEBUG, format="%(message)s")

两个点,一条关系,一个subgraph

a=Node('test',name='a')
b=Node('test',name='b')
r=Relationship(a,'knows',b,since=1000)
sub=Subgraph(relationships=[r])

graph = Graph("bolt://localhost:11003", name="*****", password="******")
测试反复create node

先试试create:
反复执行下面的代码:

tx=graph.begin()
tx.create(a)
graph.commit(tx)

第一遍的log,从Log中可以看到执行成功,从neo4j中查询也是能查到一个node

Attempting to acquire read-write connection to 'neo4j'
Using connection pool <py2neo.client.ConnectionPool object at 0x0000026605283DF0>
Trying to acquire connection from pool <py2neo.client.ConnectionPool object at 0x0000026605283DF0>
Connection <py2neo.client.bolt.Bolt4x3 object at 0x0000026605283B80> acquired by thread <_MainThread(MainThread, started 10172)>
[#CDAE] C: BEGIN {'db': 'neo4j'}
[#CDAE] C: (Sent 16 bytes)
[#CDAE] S: SUCCESS {}
**[#CDAE] C: RUN 'UNWIND $data AS r\nCREATE (_:test)\nSET _ += r\nRETURN id(_)' {'data': [{'name': 'a'}]} {}**
[#CDAE] C: PULL {'n': -1, 'qid': -1}
[#CDAE] C: (Sent 96 bytes)
[#CDAE] S: SUCCESS {'t_first': 1, 'fields': ['id(_)'], 'qid': 0}
[#CDAE] S: RECORD * 1
[#CDAE] S: SUCCESS {'stats': {'labels-added': 1, 'nodes-created': 1, 'properties-set': 1}, 'type': 'rw', 't_last': 0, 'db': 'neo4j'}
[#CDAE] C: COMMIT
[#CDAE] C: (Sent 6 bytes)
[#CDAE] S: SUCCESS {'bookmark': 'FB:kcwQo7NK3Nv+SpKE636V8mZyF8oAARe2kA=='}
Releasing connection <py2neo.client.bolt.Bolt4x3 object at 0x0000026605283B80> from thread <_MainThread(MainThread, started 10172)>

执行第2,3,4,5…遍:
发现python并没有向neo4j发送什么东西,自然就不会再创建node了。也就是说,反复执行并不会重复创建node,执行merge也有类似的情况。

Attempting to acquire read-write connection to 'neo4j'
Using connection pool <py2neo.client.ConnectionPool object at 0x0000026605283DF0>
Trying to acquire connection from pool <py2neo.client.ConnectionPool object at 0x0000026605283DF0>
Connection <py2neo.client.bolt.Bolt4x3 object at 0x0000026605283B80> acquired by thread <_MainThread(MainThread, started 10172)>
[#CDAE] C: BEGIN {'db': 'neo4j'}
[#CDAE] C: (Sent 16 bytes)
[#CDAE] S: SUCCESS {}
[#CDAE] C: COMMIT
[#CDAE] C: (Sent 6 bytes)
[#CDAE] S: SUCCESS {'bookmark': 'FB:kJA='}
Releasing connection <py2neo.client.bolt.Bolt4x3 object at 0x0000026605283B80> from thread <_MainThread(MainThread, started 10172)>

可以看到,neo4j中只有这一个点:

奇怪的问题

如果在neo4j里如果我们把点和关系全部清空,再在python执行create时,也不会重新创建点和关系。而当有这种需要反复删除和创建的场景却无法创建点和关系时,问题就变的很可恶了!!

问题分析

然而这是为什么呢?需要我们对源码进行分析。通过pycharm跟踪发现,在create的过程中,会把subgraph中的nodes和relationships进行is_bound的判断,也就是判断是否已绑定过这一entity,当nodes或relationship的graph为空时,即没有graph与entity绑定,则会创建这个entity,如果不为空,则认为entity已经和graph绑定了,也就是创建过了,所以也就不会重复创建了。

但是这个设计会带来被删除的实体无法重复创建的问题。

        node_dict = {}
        for node in self.nodes:
            if not self.**_is_bound**(node, tx.graph):
                key = frozenset(node.labels)
                node_dict.setdefault(key, []).append(node)

        # Convert relationships into a dictionary of
        #   {rel_type: [Rel, Rel, ...]}
        rel_dict = {}
        for relationship in self.relationships:
            if not self.**_is_bound**(relationship, tx.graph):
                key = type(relationship).__name__
                rel_dict.setdefault(key, []).append(relationship)
    def _is_bound(cls, entity, graph):
        if entity.graph is None:
            return False
        elif entity.graph == graph:
            return True
        else:
            raise ValueError("Entity %r is already bound to graph %r" % (entity, graph))
解决思路

如果在neo4j中已经删除node或relationship,但想利用py2neo重复创建点,可以把这个entity的graph赋值为None,就可以再次创建了。

a.graph=None

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/737664.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存