在Neo4J图上实现多个更新的正确方法是什么?

时间:2015-10-07 15:05:28

标签: java scala neo4j cypher

我在Neo4J上切齿。我试图了解在Graph DB上实现多个同时更改的正确方法是什么。

在开始之前,让我澄清一下,由于几个原因,我必须在Java / Scala应用程序中使用Neo4J作为嵌入式数据库,而不是作为我可以抛出REST调用的远程服务器。此外,我必须使用Cypher构建命令并使用Neo4J的Java API执行:exectureQuery

所以,这里有一段代码来举例说明我要做的事情:

val db = new TestGraphDatabaseFactory().newImpermanentDatabase()
val query1 =
  """
    |Create (d: Dish {name:"Fish Curry",from:"India"}),
    |(t: Table {no: 1}),
    |(d)-[r:ORDERED_FROM]->(t)
  """.stripMargin
val query2 =
    """
    |Match (d:Dish {name: "Fish Curry"}), 
    |(t: Table {no: 1}), 
    |(d)-[r:ORDERED_FROM]->(t)
    |Delete r
    """.stripMargin

val query3 =
  """
   |Match (d:Dish {name: "Fish Curry"}), (t: Table {no: 1})
   |Create (d)-[r:SERVED_AT]->(t)
  """.stripMargin

假设我在一家餐馆塑造一个典型的夜晚。我从菜单中选择一个特定的菜肴并下订单。此时, query1 被触发。创建节点和关系。

val v1 = db.execute(query1).resultAsString()
// ... I consume 'v1' appropriately 

经过一段时间后,菜已准备就绪并送达。现在,为了反映发生了什么,要触发以下命令:

val v2 = db.execute(query2).resultAsString
val v3 = db.execute(query3).resultAsString

详细说明(无论如何这对所有Neo4J专家来说都是显而易见的),我正在切断碟子和桌子之间 ORDERED_FROM 的关系,并通过 SERVED_AT <的关系将它们绑在一起/ em>的

我有两个问题:

  1. 因为我通过两个单独的Cypher查询进行了2次更新,所以我可能在交易保证上缺失。在删除旧关系和添加新关系之间, dish 容易受到另一个正交更新(可能是另一个执行线程)。如果这种理解是正确的,那么我必须做些什么来阻止它?

  2. 在上面的示例中, Dish 节点的属性是硬编码的。但是,在实践中,这些将是变量,它们的值在运行时分配。因此,在执行查询{2,3}时,可能找不到 Dish Table 。处理这个问题的正确方法是什么?如果我正确理解API,可能不会抛出任何异常。

  3. 我搜索了各种博客和其他网站以找到答案,但我没有。所以,如果我正在寻找的答案已经存在,请指出这一点。

    感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您必须在查询执行之外启动事务。否则,Cypher将为一个查询启动隐式tx。

try (Transaction tx= db.beginTx()) {
   db.execute(query1,params).close();
   db.execute(query1,params).close();
   tx.success();
}

请注意,这会使用try-with-resource,否则您必须手动调用tx.close()