简体   繁体   English

py2neo没有在Neo4j数据库中强制执行唯一性约束

[英]py2neo not enforcing uniqueness constraints in Neo4j database

I have a neo4j database with nodes that have labels "Program" and "Session". 我有一个带有标签为“ Program”和“ Session”的节点的neo4j数据库。 In the Neo4j database I've enforced a uniqueness constraint on the properties: "name" and "href". 在Neo4j数据库中,我对属性“名称”和“ href”施加了唯一性约束。 From the :schema 从:schema

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

I want to periodically query another API (thus storing the name and API endpoint href as properties), and only add new nodes when they're not already in the database. 我想定期查询另一个API(因此将名称和API端点href存储为属性),并且仅当新节点不在数据库中时才添加它们。

This is how I'm creating the nodes: 这就是我创建节点的方式:

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')

I'm running into the following error: 我遇到以下错误:

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'

My thought was that if I try to add the nodes and they're already in the database they just won't be added. 我的想法是,如果我尝试添加节点并且它们已经在数据库中,那么就不会添加它们。

I've done a try/except AttributeError block around the creation/add_labels lines, but when I did that I managed to duplicate everything that was already in the database, even though I had the constraints shown. 我已经在creation / add_labels行周围完成了一个try / except AttributeError块,但是当我这样做时,即使有显示的约束,我也设法复制了数据库中已经存在的所有内容。 (?!?) (How can py2neo manage to violate those constraints??) (?!?)(py2neo如何克服这些约束?

I'm really confused, and would appreciate any help in figuring out how to add nodes only when they don't already exist. 我真的很困惑,希望能帮助您确定仅在节点不存在时如何添加节点。

The problem seems to be that you are first creating nodes without a label and then subsequently adding the label after creation. 问题似乎在于,您首先要创建不带标签的节点,然后在创建后添加标签。

That is 那是

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

and

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

This, first creates nodes without any labels which means the nodes satisfy the constraint conditions which only apply to nodes with the labels Program and Session . 首先,创建没有标签的节点,这意味着节点满足仅适用于带有标签ProgramSession的节点的约束条件。

Once you call newprogram.add_labels('Program') and newsession.add_labels('Session') Neo4j attempts to add labels to the node and raises an exception since the constraint assertions cannot be met. 一旦调用newprogram.add_labels('Program')newsession.add_labels('Session') Neo4j newsession.add_labels('Session')尝试将标签添加到节点并引发异常,因为无法满足约束声明。

Py2neo may be creating duplicate nodes. Py2neo可能正在创建重复节点。 Although I'm sure if you inspect them, you'll find one set of nodes has the labels and the other set does not. 尽管我确定是否检查了它们,但是您会发现一组节点具有标签,而另一组则没有标签。

Can you use py2neo in a way that it adds the label at the same time as creation? 可以使用py2neo来在创建时同时添加标签的方式吗?

Otherwise you could use a Cypher query 否则,您可以使用Cypher查询

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

Using Py2neo you should be able to do this as suggested in the docs 使用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)

Firstly, the stack trace that you've shown highlights aa bug that should be fixed in the latest version of py2neo (1.6.4 at the time of writing this). 首先,您显示的堆栈跟踪突出显示了一个错误,该错误应在最新版本的py2neo(撰写本文时为1.6.4)中进行修复。 There was an issue whereby error detail dropped an expected "exception" key and this has now been fixed so upgrading should give you a better error message. 存在一个问题,错误详细信息删除了预期的“ exception”键,并且此问题已得到解决,因此升级应为您提供更好的错误消息。

However, this only addresses the error reporting bug. 但是,这仅解决了错误报告错误。 In terms of the constraint question itself, it is correct that the node creation and application of labels are necessarily carried out in two steps. 就约束问题本身而言,节点的创建和标签的应用必须分两步执行是正确的。 This is due to a limitation in the REST API that does not allow a direct method for creating a node with label detail. 这是由于REST API中的限制所致,不允许使用直接方法来创建带有标签详细信息的节点。

The next version of py2neo will make this easier/possible in a single step via batching. py2neo的下一个版本将通过批处理在一个步骤中使此操作更容易/可行。 But for now, you probably want to look at a Cypher statement to carry out the creation and labelling as mentioned in the other answer here. 但就目前而言,您可能想要查看Cypher语句来执行创建和标记,如此处其他答案所述。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM