zoukankan      html  css  js  c++  java
  • Neo4j 第五篇:批量更新数据

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

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

    我的Neo4j系列的文章收录在:Neo4j

    一,参数和UNWIND子句

    1,通过RESTful API传递参数

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

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

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

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

    注意:在HTTP API中,引用参数的格式是:{param}。

    复制代码
    {
      "statements" : [ {
        "statement" : "CREATE (n {props}) RETURN n",
        "parameters" : {
          "props" : {
            "name" : "My Node"
          }
        }
      } ]
    }
    复制代码

    2,展开(UNWIND)子句

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

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

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

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

    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,

    Package-Install Neo4jClient

    1,连接Neo4j数据库

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

    复制代码
    private GraphClient _client;
    public Neo4jClientProvider()
    {
        _client = new GraphClient(new Uri("http://localhost:7474/db/data"), "user_name", "password");
        _client.Connect();
    }
    复制代码

    2,批量创建节点

    传递List<T>参数,通过Unwind函数引用List,并为参数命名为"ns",在Cypher语句中引用参数"ns"

    复制代码
    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<T>参数中,传递两个节点的映射,在Neo4j数据库中,关系必须具有类型,因此,在把参数传递到Neo4j数据中时,需要确定两个节点和关系类型,以创建关系

    复制代码
    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();
    }
    复制代码

    参考文档:

    3.3.6. UNWIND

    Getting Started with Neo4j in .NET with Neo4jClient Library

    Batch insert nodes and relations neo4jclient

    5 Tips & Tricks for Fast Batched Updates of Graph Structures with Neo4j and Cypher

    关于Neo4j和Cypher批量更新和批量插入优化的5个建议

  • 相关阅读:
    UNP学习第八章udp
    UNP学习第七章
    linux IPC 消息队列(二)
    epoll学习(二)
    epoll学习
    UNP学习第六章(二)
    UNP学习第六章select
    UNP学习第五章(二)
    UNP学习第五章
    UNP学习第四章tcp
  • 原文地址:https://www.cnblogs.com/wangsicongde/p/7551118.html
Copyright © 2011-2022 走看看