今天主要学习的内容为图数据库neo4j,结合以往对数据库的了解以及新的知识,写一些自己的想法。
一、NoSQL数据库
对于这个知识点,我很早之前就想总结一下自己的了解,但是一值没有时间与机会,今天正好借着neo4j来总结。
特点
相对于传统数据库来说,NoSQL数据库通常具有以下一个或几个特点:
- 灵活的可扩展性,比如redis
- 灵活的数据模型,比如今天要提到的neo4j
- 与云计算紧密结合,比如hbase
NoSQL数据库的类型
NoSQL大体可以分为四种类型:键值数据库、列族数据库、文档数据库、图数据库
键值数据库(就是一堆的键值对)
数据模型:键是一个字符串对象,值可以是任意类型的数据,比如整型、字符型、数组、列表、集合等
典型应用:
- 设计频繁读写、拥有简单数据模型的应用
- 内容缓存,如会话、配置文件、参数、购物车等
- 存储配置和用户数据信息等移动应用
优点:扩展性好、灵活性好、大量写操作性能高
缺点:无法存储结构化信息,条件查询效率较低
不适用情形:
- 键值数据库根本没有通过值查询的途径
- 在键值数据库中,不能通过两个或者两个以上的键来关联数据
- 在一些键值型数据库中,产生故障时,不可以回滚
应用
- 通常,在使用键值数据库时,可以考虑将其作为缓存层,即用户通过浏览器访问底层数据库时,第一次从底层数据库取得数据,第二次之后便从键值数据库取得数据。
- Redis支持持久化、支持数据恢复,也可以提供更多数据类型
列族数据库(如HBase)
HBase根据列族进行垂直划分,根据行键进行水平划分
数据模式:列族
典型应用:
- 分布式数据存储和管理
- 数据在地理上分布于多个数据中心的应用程序
- 可以容忍副本中存在短期不一致情况的应用程序
- 拥有动态字段的应用程序
优点:查找速度块、可扩展性强、容易进行分布式扩展、复杂性低
缺点:功能比较少,大都不支持强事务一致性
不适用情形:需要ACID事务支持的情形
文档数据库
可看作键值数据库,它的值是文档而不是标量
特性:
- 能够将他自己的数据的内容和类型进行自我描述
- 与之相反,关系型数据库必须在已知schema信息的时候才能理解数据的含义
文档数据库的数据结构:JSON数据格式
文档数据库可以完整包含在一个文档里,具有较好的并发性。在对数据进行更新时,只要锁定一个文档就可以把相关数据改掉
相关产品:MongoDB
典型应用:
存储、索引并管理面向文档的数据,或者类似的半结构化数据
优点:
- 性能好(高并发),灵活性高
- 提供嵌入式文档功能,将经常查询的数据存储在同一个文档中
缺点:缺乏统一的查询语法
典型应用:存储、索引并管理面向文档的数据,或者类似的半结构化数据
不适用情形:
文档数据库不支持文档之间的事务,如果对这方面有要求就不应该选用这个方案
图数据库
相关产品:Neo4j
数据模型:图结构
典型应用:专门用来处理具有高度相关关联关系的数据,比较适合于社交网络、模式识别、依赖分析、推荐系统以及路径寻找等问题
优点:灵活性高,支持复杂的图形算法;可用于构建复杂的关系图谱
缺点:数据模型应用范围非常有限
二、neo4j
neo4j即上文所提到的图数据库的代表,它可以用于存储更多的连接数据,即上面提到的高度相关或关联的数据。
对于我这样的初学者来说,最关心的内容就是这个数据库的使用问题,而neo4j支持的语言并不是关系型数据库常用的SQL,而是一种名为CQL(Cypher查询语言)的语言。
而对于CQL的学习,则必须参考neo4j教程(仅仅是我的推荐)https://www.w3cschool.cn/neo4j/。
三、与python进行交互
neo4j与python进行交互主要通过两个模块,一个是neo4j模块,一个是py2neo模块。
1.neo4j模块
#导入驱动包
from neo4j import GraphDatabase
#连接neo4j数据库
driver = GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "123456"))
##添加关系函数
def add_friend(tx, name, friend_name):
tx.run("MERGE (a:Person {name: $name}) "
"MERGE (a)-[:KNOWS]->(friend:Person {name: $friend_name})",
name=name, friend_name=friend_name)##括号里的CQL意义为,创建一个标签为Person的点,并为其赋予属性name,然后对这个点加上关系KNOWS与另一个Person相连,当然也可以简单理解为创建一个人,并给他一个女朋友
# 定义关系函数
def print_friends(tx, name):
for record in tx.run("MATCH (a:Person)-[:KNOWS]->(friend) WHERE a.name = $name "
"RETURN friend.name ORDER BY friend.name", name=name):
print(record["friend.name"]) #其实这个地方应该只是把符合要求的人姓名匹配到并依次打印,好像并未起到定义关系的作用,此处存疑
# step 3:运行
with driver.session() as session:
session.write_transaction(add_friend, "Arthur", "Guinevere")
session.write_transaction(add_friend, "Arthur", "Lancelot")
session.write_transaction(add_friend, "Arthur", "Merlin")
session.read_transaction(print_friends, "Arthur")
2.py2neo模块
相比neo4j,这个包确实更加贴合python用户,即使不会CQL,也可以六到飞起。
# step 1:导包
from py2neo import Graph, Node, Relationship
# step 2:构建图
g = Graph()
# step 3:创建节点
tx = g.begin()
a = Node("Person", name="Alice")
tx.create(a)
b = Node("Person", name="Bob")
# step 4:创建边
ab = Relationship(a, "KNOWS", b)
# step 5:运行
tx.create(ab)
tx.commit()