Python使用Py2neo创建Neo4j的节点和关系
作者:流浪猫猫 发布时间:2023-07-20 02:51:45
目录
一、安装Py2neo
二、连接Neo4j数据库
1. 使用graph.run执行Cypher语句创建节点
2. 使用Node数据结构创建节点
3. 使用Node、Relationship和Subgraph数据结构创建节点和关系
三、性能对比
Neo4j是一款开源图数据库,使用Python语言访问Neo4j可以使用Py2neo。本文介绍了使用Py2neo访问Neo4j,批量创建节点和关系的方法。Py2neo提供了直接执行Cypher语句的方法,也提供了诸如Node、Relationship、Path一系列的数据结构,在不同的场景下可以灵活使用。
本文使用的Py2neo是2021.1之后的版本,手册请戳这里:
The Py2neo Handbook
一、安装Py2neo
使用pip安装Py2neo,执行:
pip install py2neo
查看已安装的Py2neo是什么版本的:
pip show py2neo
二、连接Neo4j数据库
本文中会用到多种数据类型,在此一并引用
import numpy as np
import pandas as pd
from py2neo import Node,Relationship,Graph,Path,Subgraph
配置Neo4j数据库的访问地址、用户名和密码
neo4j_url = '访问地址'
user = '用户名'
pwd = '密码'
在此时间段之前访问数据库的方式为:
graph = Graph(neo4j_url, username=user, password=pwd)
在此时间段之后的版本访问数据库的方式为(就是这么不兼容):
graph = Graph(neo4j_url, auth=(user, pwd))
1. 使用graph.run执行Cypher语句创建节点
如果熟悉Cypher语句的话,可以通过使用graph.run执行Cypher语句来实现创建节点等操作,方法如下所示:
cypher_ = "CREATE (:Person {name:'王王', age:35, work:'脚本之家}),\
(:Person {name:'李李', age:20, work:'脚本之家})"
graph.run(cypher_)
这样就在Neo4j中创建了两个label为Person的节点,第一个节点的name属性为“王王”,age属性为35,work属性为“脚本之家”,第二个节点的name属性为“李李”,age属性为20,work属性为“宇脚本之家”。
同样,可以通过调用graph.run执行Cypher语句
创建关系。
cypher_ = "MATCH (from:Person{name:'王王'}),\
(to:Person{name:'李李'}) MERGE (from)-[r:同事]->(to)"
graph.run(cypher_)
这样在Neo4j中就有了具有同事关系的两个Person节点。
2. 使用Node数据结构创建节点
Py2neo也提供graph.create方法来创建节点和关系
node = Node("Person", name="李李", age=20, work="脚本之家")
graph.create(node)
与执行Cypher语句的效果相同,在Neo4j中创建了一个Person节点。
需要注意的是,这两种创建方法,如果反复执行的话,是会在Neo4j中创建出重复的节点的,即name、age、work属性完全一样,但在Neo4j中的id不一样的多个节点。
3. 使用Node、Relationship和Subgraph数据结构创建节点和关系
上面两种方法都是一次创建一个节点或者一个关系,Py2neo也提供了批量创建节点和关系的方法,而且性能更优。下面就以下图中的图谱为例,使用Py2neo提供Node、Relationship和Subgraph数据结构在Neo4j中创建节点和关系。
首先创建一些label为Person的节点,即Node对象,第一个参数是label,属性按key=value依次作为参数传入。如果节点有多个label,可以用Node.add_label("label_text")
来追加label。
node1 = Node("Person", name="王王", age=35, work="脚本之家")
node2 = Node("Person", name="李李", age=20, work="脚本之家")
node3 = Node("Person", name="张张", age=30, work="脚本之家")
node4 = Node("Person", name="赵赵", age=45, work="月亮中学")
node4.add_label("Teacher")
node5 = Node("Person", name="刘刘", age=20, work="地球电子商务公司")
再创建一些label为Location的节点
node6 = Node("Location", name="南京")
node7 = Node("Location", name="江宁区")
node8 = Node("Location", name="禄口机场")
建立一些Person和Person节点之间的关系,Neo4j中的关系是有方向的,所以Relationship第一个参数为起始节点,第三个参数是结束节点,而第二个节点为关系的类型。这里创建的同事、邻居的关系为双向的,老师、学生的关系为单向。
relation1 = Relationship(node1, "同事", node2)
relation2 = Relationship(node2, "同事", node1)
relation3 = Relationship(node2, "同事", node3)
relation4 = Relationship(node3, "同事", node2)
relation5 = Relationship(node3, "邻居", node4)
relation6 = Relationship(node4, "邻居", node3)
relation7 = Relationship(node4, "学生", node5)
relation8 = Relationship(node5, "老师", node4)
创建一些Location和Location节点之间的关系,地域之间的包含关系为单向。
relation9 = Relationship(node6, "包含", node7)
relation10 = Relationship(node7, "包含", node8)
创建Person节点和Location节点之间的关系,这里“到访”的关系是有属性的,date表示到访的日期,stay_hours表示停留的时间。可以使用一个key:value的字典数据结构保存属性,再赋予关系
properties1={'date':'2021-7-16','stay_hours':1}
relation11 = Relationship(node2, "到访", node8, **properties1)
properties2={'date':'2021-7-19','stay_hours':4}
relation12 = Relationship(node5, "到访", node8, **properties2)
然后将以上所有节点和关系组成Subgraph
node_ls = [node1, node2, node3, node4,
node5, node6, node7, node8]
relation_ls = [relation1, relation2, relation3, relation4,
relation5, relation6, relation7, relation8,
relation9, relation10, relation11, relation12]
subgraph = Subgraph(node_ls, relation_ls)
最后通过事务类Transaction提交,批量创建这些节点和关系。这里tx.create并没有真正创建节点和关系,直到graph.commit才一次性提交到Neo4j进行创建。
tx = graph.begin()
tx.create(subgraph)
graph.commit(tx)
重复执行上面的命令,不会创造出重复的节点和关系。这一点手册中有说明:“subgraph中的已经和数据库绑定的实体将保持不变,那些没有绑定的将在数据库中新建并绑定上。”
create(subgraph) Create remote nodes and relationships that correspond to those in a local subgraph. Any entities in subgraph that are already bound to remote entities will remain unchanged, those which are not will become bound to their newly-created counterparts.
三、性能对比
做一个简单的实验粗略地对比逐个创建和批量创建的时间开销。在Neo4j为空数据库的情况下,分别采用逐个创建和批量创建的方法创建10000个节点,每个节点有name和age两个属性,都是随机生成的,使用jupyter notebook的%%time命令计算时间开销。
import random
N = 10000
逐个创建节点:
%%time
for i in range(N):
random_name = "P"+str(round(random.random()*N*2))
random_age = round(random.random()*15)
node = Node("Person", name=random_name, age=random_age)
graph.create(node)
CPU times: user 50.3 s, sys: 4.19 s, total: 54.5 s
Wall time: 5min 16s
批量创建节点:
%%time
node_ls = []
for i in range(N):
random_name = "P"+str(round(random.random()*N*2))
random_age = round(random.random()*15)
node = Node("Person", name=random_name, age=random_age)
node_ls.append(node)
subgraph = Subgraph(node_ls, [])
tx = graph.begin()
tx.create(subgraph)
graph.commit(tx)
CPU times: user 448 ms, sys: 75.5 ms, total: 523 ms
Wall time: 1.46 s
实验中也发现,只是创建节点的话,批量创建方法的时间开销几乎是线性增长的,当一次性提交10万个节点的创建任务时,时间开销大约在4.5秒。
在使用Py2neo构建图谱时,尽可能使用批量创建方法。先创建节点(Node)对象、关系(Relationship)对象,再构成子图(Subgraph),最后利用事务类一次提交创建。
下一篇将介绍如何运用Py2neo查询节点、关系和路径。
来源:https://segmentfault.com/a/1190000040519140


猜你喜欢
- ACID:Atomic、Consistent、Isolated、Durable 存储程序提供了一个绝佳的机制来定义、封装和管理事务。 1,M
- 本文实例为大家分享CentOS 7.2 Yum安装mysql5.6的方法,供大家参考,具体内容如下配置CentOS SCLo源[3] 添加
- BinLogBinLog是记录所有数据库表结构变更(例如create、alter table)以及表数据修改(insert、update、d
- 本文实例讲述了Python针对给定字符串求解所有子序列是否为回文序列的方法。分享给大家供大家参考,具体如下:问题:给定一个字符串,得到所有的
- javascript实现炫酷的拖动分页js<html><head><title>拖动分页</tit
- 前言: 经过前面文章学习,我们知道 binlog 会记录数据库所有执行的 DDL 和 DML 语句(除了数据查询语句select、
- 这篇文章主要介绍了用python写测试数据文件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 用FrontPage做网页的朋友们,你的主要页面中,可能都带有许多相同的元素吧?如页头横向排列(或左侧纵向排列)的主要链接按钮、页底的板权说
- 1.理解mask()和setmask()一般是在pyqt绘图时常见,而且在显示不规则图形时更是常见。参考书籍上说:setMask()函数的作
- 今天咱写一个挺实用的工具,就是扫描并获取可用的proxy首先呢,我先百度找了一个网站:http://www.xicidaili.com 作为
- 制作初衷:外地开了票到公司后发现信息有错误,无法报销;公司的行政和财务经常在工作日被问及公司开票信息,影响心情和工作;引入相应的专业APP来
- 过滤器模板层对变量的操作实际还有很多,过滤器就是其中一种。学过Linux系统的一定知道管道操作符,其可以将上一步输出直接作为下一步输入进行处
- 理论Python中不存在真正的私有方法。为了实现类似于c++中私有方法,可以在类的方法或属性前加一个“_”单下划线,意味着该方法或属性不应该
- 本文实例讲述了python爬虫学习笔记之Beautifulsoup模块用法。分享给大家供大家参考,具体如下:相关内容:什么是beautifu
- 在做web端自动化测试用例编写过程中,大家有没有遇到窗口切换的情况,比如如下截图所示的商品列表页,点击任何一款产品后切换到这块产品详情页的情
- 我们有时候看到一篇好的文章,想去保存下来,传统方式一般是收藏书签、复制粘贴到文档或者直接复制链接保存,但这样一次两次还好,数量多了,比较麻烦
- PyQt5多行文本框控件QTextEdit简介QTextEdit类是一个多行文本框控件,可以显示多行文本内容,当文本内容超出控件显示范围时,
- mergemerge 函数通过一个或多个键将数据集的行连接起来。场景:针对同一个主键存在的两张包含不同特征的表,通过主键的链接,将两张表进行
- 这篇文章主要介绍了Python函数参数类型及排序原理总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- 解决MySql 数据库 提示:1045 access denied for user 'root'@'localho