Драйвер Neo4j - подтвердить успешность транзакции
Я только начал играть с новым драйвером neo4j для python и полностью застрял в транзакциях. Как проверить, успешно ли завершена транзакция? Насколько я могу сказать commit
Функция не вызывает автоматически никаких ошибок, т.е. если, например, я предоставляю ей неправильный запрос Cypher, я не получаю никакой информации по этому вопросу.
Я пытался читать last_result
аргумент от Session
объект и придумал что-то вроде:
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 могут быть идентифицированы уже во время выполнения запросов.
2 ответа
Я бился головой об одном и том же, пока не прочитал руководство для разработчика.
До этого я не мог понять, почему несколько плохих утверждений с 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()
Надеюсь, это поможет другим.