py2neo не применяет ограничения уникальности в базе данных Neo4j

У меня есть база данных neo4j с узлами, у которых есть ярлыки «Программа» и «Сессия». В базе данных Neo4j я установил ограничение уникальности для свойств: «name» и «href». Из: схемы

Constraints
ON (program:Program) ASSERT program.href IS UNIQUE
ON (program:Program) ASSERT program.name IS UNIQUE
ON (session:Session) ASSERT session.name IS UNIQUE
ON (session:Session) ASSERT session.href IS UNIQUE

Я хочу периодически запрашивать другой API (таким образом, сохраняя имя и href конечной точки API как свойства) и добавлять новые узлы только тогда, когда их еще нет в базе данных.

Вот как я создаю узлы:

newprogram, = graph_db.create(node(name = programname, href = programhref))
newprogram.add_labels('Program')

newsession, = graph_db.create(node(name = sessionname, href = sessionhref))
newsession.add_labels('Session')

У меня следующая ошибка:

Traceback (most recent call last):
  File "/Users/jedc/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "/Users/jedc/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "/Users/jedc/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/Users/jedc/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/Users/jedc/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/Users/jedc/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/Users/jedc/appfolder/applicationapis.py", line 42, in post
    newprogram.add_labels('Program')
  File "/Users/jedc/appfolder/py2neo/util.py", line 99, in f_
    return f(*args, **kwargs)
  File "/Users/jedc/appfolder/py2neo/core.py", line 1638, in add_labels
    if err.response.status_code == BAD_REQUEST and err.cause.exception == 'ConstraintViolationException':
AttributeError: 'ConstraintViolationException' object has no attribute 'exception'

Я думал, что если я попытаюсь добавить узлы, а они уже находятся в базе данных, они просто не будут добавлены.

Я сделал блок try / except AttributeError вокруг строк create / add_labels, но когда я это сделал, мне удалось продублировать все, что уже было в базе данных, даже несмотря на то, что у меня были показанные ограничения. (?!?) (Как py2neo может нарушить эти ограничения ??)

Я действительно смущен и был бы признателен за любую помощь в выяснении того, как добавлять узлы только тогда, когда они еще не существуют.


person Jed Christiansen    schedule 08.07.2014    source источник
comment
Ограничение не будет нарушено, пока вы не добавите метку, что вы делаете после создания узла. Итак, узел создан, но add_label должен завершиться ошибкой.   -  person Nicole White    schedule 08.07.2014
comment
Думаю, другой вопрос: могу ли я добавить ограничения, не привязанные к ярлыкам? (Полагаю, что не могу.)   -  person Jed Christiansen    schedule 08.07.2014
comment
Вы можете сделать одно заявление? graph.create (узел) .add_label ()?   -  person Nicole White    schedule 08.07.2014


Ответы (2)


Проблема, похоже, в том, что вы сначала создаете узлы без метки, а затем добавляете метку после создания.

Это

graph_db.create(node(name = programname, href = programhref))

и

graph_db.create(node(name = sessionname, href = sessionhref))

Это сначала создает узлы без каких-либо меток, что означает, что узлы удовлетворяют условиям ограничения, которые применяются только к узлам с метками Program и Session.

После вызова newprogram.add_labels('Program') и newsession.add_labels('Session') Neo4j пытается добавить метки к узлу и вызывает исключение, поскольку утверждения ограничений не могут быть выполнены.

Py2neo может создавать повторяющиеся узлы. Хотя я уверен, что если вы их осмотрите, вы обнаружите, что один набор узлов имеет метки, а другой - нет.

Можете ли вы использовать py2neo таким образом, чтобы метка добавлялась одновременно с созданием?

В противном случае вы можете использовать запрос Cypher

CREATE (program:Program{name: {programname}, href: {programhref}})
CREATE (session:Session{name: {sessionname}, href: {sessionhref}})

Используя Py2neo, вы должны иметь возможность сделать это, как это предлагается в документации

graph_db = neo4j.GraphDatabaseService()
qs = '''CREATE (program:Program{name: {programname}, href: {programhref}})
        CREATE (session:Session{name: {sessionname}, href: {sessionhref}})'''
query = neo4j.CypherQuery(graph_db, qs)
query.execute(programname=programname, programhref=programhref,
              sessionname=sessionname, sessionhref=sessionhref)
person stephenmuss    schedule 08.07.2014
comment
Ну конечно. Я пробовал несколько разных подходов и просто обвился вокруг оси. Я реализовал это и теперь получаю сообщение об ошибке в строке query.execute с ParameterNotFoundException: ожидался параметр с именем programname. Я ошибаюсь в синтаксисе? - person Jed Christiansen; 08.07.2014
comment
Я забыл пробел в аргументе qs между name: и {programname}, так что это решено. Теперь мне просто нужно выяснить, как получить результаты CypherQuery! - person Jed Christiansen; 08.07.2014

Во-первых, трассировка стека, которую вы показали, указывает на ошибку, которая должна быть исправлена ​​в последней версии py2neo (1.6.4 на момент написания этой статьи). Возникла проблема, из-за которой в подробных сведениях об ошибке пропадал ожидаемый ключ «исключение», и теперь это исправлено, поэтому при обновлении должно отображаться более четкое сообщение об ошибке.

Однако это только устраняет ошибку сообщения об ошибке. Что касается самого вопроса ограничения, правильно, что создание узла и применение меток обязательно выполняется в два этапа. Это связано с ограничением REST API, которое не позволяет использовать прямой метод для создания узла с деталями метки.

Следующая версия py2neo сделает это проще / возможным за один шаг с помощью пакетной обработки. Но пока вы, вероятно, захотите взглянуть на инструкцию Cypher для выполнения создания и маркировки, как указано в другом ответе здесь.

person Nigel Small    schedule 09.07.2014
comment
Спасибо за дополнительный контекст, Найджел! Я обновлюсь до последней версии. И с тех пор у меня есть все, чтобы работать с запросами Cypher в соответствии с ответом выше. - person Jed Christiansen; 09.07.2014