我刚刚开始使用python的新neo4j驱动程序,但完全被事务所困扰。如何检查交易是否成功完成?就我所能说的,commit
函数不会自动引发任何错误,例如,如果我向它提供了一个不正确的Cypher查询,我就得不到任何信息。
我试着从Session
对象中读取last_result
自变量,并想出了一些类似的东西:
import neo4j.v1 as neo
def db_confirm_transaction_success(session):
try:
w = list(session.last_result)
return True
except neo.CypherError as e:
session.last_result._consumed = True
return False
except neo.ResultError as e:
session.last_result._consumed = True
return False
这有点奏效。。。然而,它确实需要修改私有属性,而且看起来根本不正确。必须有一个更简单、更优雅的解决方案。
提前感谢您的帮助。
编辑:只是为了明确Transaction.success
属性指示事务应该提交还是回滚。然而,例如,Cypher错误可以被识别为查询执行时间较晚。
在阅读开发人员手册之前,我一直在做同样的事情。
在那之前,我不明白为什么用session.run(statement)
运行几个坏语句不会引发异常,而session.close()
会引发异常。
然后我试着使用类似的东西:
with session.begin_transaction() as tx:
tx.run(statement)
tx.success = True
如果你不想要上下文管理器,你可以使用:
tx = session.begin_transaction()
tx.run(statement)
tx.commit()
如果您阅读了python文档,您可能会注意到tx.commit()
与运行tx.success=True
和tx.close()
是一样的。
这样做的问题是,调用commit()
只会将COMMIT
密码消息附加到连接的流中。据我所知,它并不能验证交易的成功。
在阅读了手册中的第18节后,我发现由于我没有明确地使用结果,因此无法保证该语句得到处理,因为库使用了延迟加载(仅按需检索结果)。参见下面18.1中的注释:
"当光标在流中移动时,结果记录被延迟加载意味着必须将光标移动到第一个结果,然后才能显示此结果消耗。这也意味着在摘要信息和元数据是可用的。通常最佳做法是显式使用结果并关闭会话,尤其是在运行更新时声明。即使不需要摘要信息,这也适用。未能消费一个结果可能导致不可预测的行为,因为无法保证服务器已经看到并处理了Cypher语句。">
因此,本质上,您需要在运行一个密码语句后显式使用结果。可以这样做:
res = session.run(statement) # or the equivalent iusing transaction style
res.consume()
我注意到.consume()
函数调用list(self)
来迭代所有结果(StatementResult类定义了一个__iter__
方法)。因此,虽然我还没有测试过它,但可能是这样的情况,即简单地在结果上循环会为您带来消耗:
res = session.run(statement)
for r in res:
continue
希望这能有所帮助!
只是想发布Neo4j 4.x
的更新答案。
def commit_data(query):
with driver.session(database="neo4j") as session:
tx = session.begin_transaction()
result = tx.run(query)
result = [dict(i) for i in result]
# uncomment below line to see the complete txn summary.
# print(result)
if result[0]['failedOperations']>0:
print(query)
print(result)
raise 'Error! Please recheck your query.'
tx.commit()
希望它能帮助其他人。