Neo4j-5-BatchUpdate

Neo4j 第五篇:批量更新数据

转载:https://www.cnblogs.com/ljhdo/p/5554560.html

参考:
https://neo4j.com/docs/cypher-manual/current/clauses/unwind/
https://www.tugberkugurlu.com/archive/getting-started-with-neo4j-in--net-with-neo4jclient-library
https://neo4j.com/docs/cypher-manual/current/clauses/foreach/
https://blog.csdn.net/hwz2311245/article/details/60963383

相比图形数据的查询,Neo4j 更新图形数据的速度较慢,通常情况下,Neo4j 更新数据的工作流程是:每次数据更新都会执行一次数据库连接,打开一个事务,在事务中更新数据。当数据量非常大时,这种做法非常耗时,大多数时间耗费在连接数据库和打开事务上,高效的做法是利用Neo4j提供的参数(Parameter)机制和UNWIND子句:在一次数据更新中,进行一次连接,打开一次事务,批量更新数据;参数用于提供列表格式的数据,UNWIND 子句是把列表数据展开成一行一行的数据,每行数据都会执行结构相同的 Cypher 语句。再批量更新图形数据之前,用户必须构造结构固定的、参数化的 Cypher 语句。当 Cypher 语句的结构相同时,Neo4j 数据库直接从缓存中复用已生成的执行计划,而不需要重新生成,这也能够提高查询性能。

除了官方的 Neo4j Driver 之外,本文分享使用 Neo4jClient 对图形数据批量更新,Neo4jClient 提供的功能更强大,并支持参数和批量更新操作。

一 参数 和 UNWIND 子句

1 通过 RESTful API 传递参数

Neo4j 提供 HTTP API 处理 Cypher 语句和参数,在示例代码中,Neo4j 参数通过 HTTP 请求传递,statement 定义的是查询语句,parameters 定义的是参数。

在批量更新数据时,没有必要发送多个 HTTP 请求,通过参数,可以在一个 HTTP 请求(Request)中,开始一个事务,在事务中执行 Cypher 语句批量更新数据,最后提交该事务。

在发送 HTTP 请求传递参数批量更新数据时,设置 HTTP Request 的参数如下:

1
2
3
POST http://localhost:7474/db/data/transaction/commit
Accept: application/json; charset=UTF-8
Content-Type: application/json

1
2
3
4
5
6
7
8
9
10
{
"statements" : [ {
"statement" : "CREATE (n {props}) RETURN n",
"parameters" : {
"props" : {
"name" : "My Node"
}
}
} ]
}

2 展开(UNWIND)子句

UNWIND 子句把列表式的数据展开成一行一行的数据,每一个行都包含更新所需要的全部信息,列表式的数据,可以通过参数来传递。

例如,定义参数 events,该参数是一个 JSON 字符串,键 events 是参数名,其值是一个数组,包含两个数组元素。

1
2
3
{
"events" : [ { "year" : 2014, "id" : 1}, {"year" : 2014, "id" : 2 } ]
}

通过 $events 引用参数,UNWIND 子句把 events 数组中的两个元素展开,每个元素执行一次 Cypher 语句,由于 Cypher 的语句结构固定,因此,执行计划被缓存起来,在执行数据更新任务时,参数被 UNWIND 子句展开,复用执行计划,提高数据更新的速度。

1
2
3
4
5
UNWIND $events AS event
MERGE (y:Year { year: event.year })
MERGE (y)<-[:IN]-(e:Event { id: event.id })
RETURN e.id AS x
ORDER BY x

二 在 Neo4j Browser 中使用参数

Neo4j Browser 是 Neo4j 内置的浏览器,用于管理数据库,更新数据库和查询数据,再命令窗体中,通过 “:” 能够引用内置的命令,例如,通过 “:param” 能够定义参数,并能够在下一个 Cypher 语句中引用参数。

1 通过 :param 命令定义参数

在 Neo4j Browser 中,输入第一个命令,通过 :param 命令定义参数,

2 通过 $param 引用参数

紧接着,输入 Cypher 语句,通过 $param 引用参数

3 查看创建的图形

参数是一个列表格式的数据,在参数 events 中,两个 event 的 year 属性都是 2014,因此,MERGE 子句只会创建一个 Year 节点;由于两个 event 的id属性不同,因此 MERGE 子句会创建两个 Event 节点,并创建 Year 节点和 Event 节点之间的关系,图形如下图:

三 使用 Neo4jClient 批量更新数据

在工程(Projects)中输入命令安装 Neo4jClient,

1
Package-Install Neo4jClient

1 连接 Neo4j 数据库

创建客户端,连接到数据库,创建的Uri的格式是:http://host_name:7474/db/data,并输入用户名和密码,然后创建图形客户端,并连接到 Neo4j 数据库。

1
2
3
4
5
6
private GraphClient _client;
public Neo4jClientProvider()
{
_client = new GraphClient(new Uri("http://localhost:7474/db/data"), "user_name", "password");
_client.Connect();
}

2 批量创建节点

传递 List 参数,通过 Unwind 函数引用 List,并为参数命名为 “ns”,在 Cypher 语句中引用参数 “ns”

1
2
3
4
5
6
7
8
9
public void CreateNodes(List<DataModel> nodes)
{
_client.Cypher
.Unwind(nodes, "ns")
.Create("(n:NodeLable)")
.Set("n.NodeID=ns.NodeID")
.Set("n.Name=ns.Name")
.ExecuteWithoutResults();
}

2 批量创建关系

在 List 参数中,传递两个节点的映射,在 Neo4j 数据库中,关系必须具有类型,因此,在把参数传递到 Neo4j 数据中时,需要确定两个节点和关系类型,以创建关系

1
2
3
4
5
6
7
8
9
public bool CreateRelationships(List<RelationshipModel> nodes)
{
_client.Cypher
.Unwind(nodes, "ns")
.Match("(n:Lable1),(s:Lable2)")
.Where("n.NodeID=ns.NodeID and s.NodeID=ns.RelatedID")
.Merge("(n)-[r:RelationshipType]->(s)")
.ExecuteWithoutResults();
}
Contents
  1. 1. Neo4j 第五篇:批量更新数据
    1. 1.1. 一 参数 和 UNWIND 子句
      1. 1.1.1. 1 通过 RESTful API 传递参数
      2. 1.1.2. 2 展开(UNWIND)子句
    2. 1.2. 二 在 Neo4j Browser 中使用参数
      1. 1.2.1. 1 通过 :param 命令定义参数
      2. 1.2.2. 2 通过 $param 引用参数
      3. 1.2.3. 3 查看创建的图形
    3. 1.3. 三 使用 Neo4jClient 批量更新数据
      1. 1.3.1. 1 连接 Neo4j 数据库
      2. 1.3.2. 2 批量创建节点
      3. 1.3.3. 2 批量创建关系
|