3

I have put together a simple test case:

account = EmailAccount()
account.email = "some@mail"
assert db.account_by_mail("some@mail") == []
db.add_node(account)
assert db.account_by_mail(account.email) == [account]
db.delete_node(account))
assert db.account_by_mail("some@mail") == []

All goes well until the last line, where an exception is thrown:

Neo.DatabaseError.Statement.ExecutionFailure: Node 226 has been deleted

The statement executed by last line is as follows:

MATCH (account:Account) WHERE account.email = {mail} RETURN account, id(account), head(labels(account))

with parameters

{
  'mail': "some@mail"
}

All of the statements are executed within same transaction(we use the py2neo Transaction class for that, wrapped in a session wrapper - db). The behavior isn't exactly in line with delete semantics (link here) as the transaction hasn't been commited and the statement is a read, not a write. Are there some other hidden constraints? Is this default behavior, and if so, can it be changed(since I assume most other dbms don't behave this way)?

poe123
  • 1,188
  • 8
  • 11
  • from your link: _It is possible to acquire a reference to a deleted relationship or node that has not yet been committed._ So Neo4j finds a reference to 226, but does not find the node since it's not been committed. – Hrabal Sep 29 '14 at 11:09

1 Answers1

0

The latest version of py2neo uses a lazy approach to node commits to avoid unnecessary amounts of network traffic (see http://py2neo.org/2.0/intro.html#nodes-relationships). As a result, you have to directly commit your changes to the graph in order for them to be persisted. Without seeing your db code more explicitly, if I understand correctly, you are not committing your transactions to the graph and, as such, you are simply modifying the state of objects not yet persisted.

This behavior is in line with other orm implementations such as SQL Alchemy (python) or Hibernate (Java) and closely mirrors the actual transactional demarcation that takes place at the dbms level.