图数据库是一种专门设计用于存储和管理图形数据的数据库类型。在图数据库中,数据以图的形式表示,其中节点表示实体,边表示实体之间的关系。这种表示方式非常适合处理具有复杂关系的数据,如社交网络、推荐系统、网络拓扑、生物信息学等领域的数据。
图数据库通常具有以下特点:
应用图数据库的场景包括:
图数据库的例子包括Neo4j、Amazon Neptune、ArangoDB等。这些数据库在处理具有复杂关系的数据时通常比传统的关系型数据库更有效。
为什么要使用图数据库:
在数据关系中心,图形数据库在查询速度方面非常高效,即使面对深度和复杂的查询也是如此。之前有人做了个实验,在一个社交网络找到最大深度为 4 的朋友的朋友,其中当深度为 4 的时候,图数据库的执行时间约为关系型数据库的 一千五百分之一,。
图数据库是以图结构存储和查询数据的数据库。在图数据库中,节点和关系取代表,外键和 Join。在图数据库中,无论何时运行类似 Join 的操作,数据库都会使用列表并直接访问链接的节点,而无需进行昂贵的搜索和匹配运算。
各个数据库的优劣点:
数据库类型 | 数据类型 | 优势 | 劣势 | 举例 |
---|---|---|---|---|
键值数据库 | 键值对 | 简单、高性能 | 不适用于复杂查询,没有内建查询语言 | Redis、DynamoDB、Riak |
列存储数据库 | 列 | 适用于大规模数据分析,压缩效果好,读取特定列的性能高 | 不适合频繁更新操作 | Apache Cassandra、HBase、Bigtable |
文档性数据库 | 文档 | 灵活,存储和查询复杂的数据结构,支持丰富的查询语言 | 处理大量数据时性能可能不如专门优化的存储引擎 | MongoDB、CouchDB、Elasticsearch |
图数据库 | 节点和边 | 高效处理复杂关系型数据,适用于网络分析、社交网络、推荐系统等 | 不适合简单查询,对于关系不是核心的应用可能过于复杂 | Neo4j、ArangoDB、Amazon Neptune |
Neo4j 是一种图数据库管理系统,专门设计用于存储和处理图形数据。主要有以下构建元素:
Neo4j 使用场景:
Neo4j 常用于欺诈检测、实时推荐引擎。Neo4j常用于欺诈检测和实时推荐引擎等应用场景,这是因为Neo4j在处理复杂关系型数据方面具有优势。
安装Neo4j可以通过Docker容器化来简化和隔离部署过程。以下是在Docker中安装Neo4j的一般步骤:
docker pull neo4j
这将从Docker Hub下载最新的Neo4j镜像。
-p
选项将Neo4j的HTTP端口映射到本地主机端口(例如,7474和7687):docker run --name my-neo4j -e "NEO4J_AUTH=neo4j/123456" -p 7474:7474 -p 7687:7687 -d neo4j
这将在后台运行Neo4j容器,并将其命名为my-neo4j
。你可以根据需要更改容器名称。
http://localhost:7474
。默认的用户名为 neo4j
,初始密码会在第一次访问时要求更改。bolt://localhost:7687
)。docker stop my-neo4j
Neo4j 的 Cypher 语言是专门为处理图形数据而构建的,CQL 代表 Cypher 查询语言。像 Oracle 数据库具有查询语言 SQL,Neo4j 具有 CQL 作为查询语言。
对于 CQL 而言,它是一种声明性模式匹配语言,遵循 SQL 语法。
简单的 CQL 命令及用法如下:
CQL 命令 | 用法 |
---|---|
CREATE | 创建节点 |
MATCH | 检索有关节点,关系和属性数据 |
RETURN | 返回查询结果 |
WHERE | 提供条件过滤检索数据 |
DELETE | 删除节点和关系 |
REMOVE | 删除节点和关系的属性 |
ORDER BY | 排序检索数据 |
SET | 添加或更新标签 |
CREATE (n:Label {property1: value1, property2: value2, ...})
CREATE (person:Person {name: 'John', age: 30})
MATCH (node1:Label1), (node2:Label2)
WHERE node1.property = value1 AND node2.property = value2
CREATE (node1)-[:RELATIONSHIP_TYPE]->(node2)
MATCH (john:Person {name: 'John'}), (jane:Person {name: 'Jane'})
CREATE (john)-[:KNOWS]->(jane)
MATCH (node:Label {property: value})-[:RELATIONSHIP_TYPE]->(relatedNode)
RETURN node, relatedNode
MATCH (person:Person {name: 'John'})-[:KNOWS]->(friend)
RETURN person, friend
MATCH (node:Label {property: value})
SET node.property = newValue
MATCH (person:Person {name: 'John'})
SET person.age = 31
MATCH (node:Label {property: value})-[relation:RELATIONSHIP_TYPE]->()
DELETE node, relation
MATCH (person:Person {name: 'John'})-[relation:KNOWS]->()
DELETE person, relation
MATCH (node:Label {property: value})-[:RELATIONSHIP_TYPE]->(relatedNode)
RETURN node, relatedNode
MATCH (person:Person {name: 'John'})-[:KNOWS]->(friend)
RETURN person, friend
MATCH (node:Label {property: value})
RETURN node.property
MATCH (person:Person {name: 'John'})
RETURN person.age
使用 Go 语言创建 Neo4j 数据库西游数据并写入 Neo4j 数据库中:
package main
import (
"fmt"
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
"log"
)
func main() {
// Neo4j数据库连接信息
neo4jURI := "bolt://43.143.147.135:27687"
username := "username"
password := "password"
// 创建Neo4j数据库驱动
driver, err := neo4j.NewDriver(neo4jURI, neo4j.BasicAuth(username, password, ""))
if err != nil {
log.Fatal(err)
}
defer driver.Close()
// 创建Neo4j数据库会话
session, err := driver.Session(neo4j.AccessModeWrite)
if err != nil {
log.Fatal(err)
}
defer session.Close()
// 定义要写入的数据
data := []string{
`CREATE (tang:Character {NodeID: 1, Name: 'TangSeng', Title: '唐僧'})`,
`CREATE (wukong:Character {NodeID: 2, Name: 'SunWukong', Title: '孙悟空'})`,
`CREATE (bajie:Character {NodeID: 3, Name: 'ZhuBajie', Title: '猪八戒'})`,
`CREATE (wujing:Character {NodeID: 4, Name: 'ShaWujing', Title: '沙悟净'})`,
`CREATE (xitian:Place {NodeID: 5, Name: 'Xitian', Title: '西天'})`,
`CREATE (journey:Task {NodeID: 6, Name: 'Journey', Title: '西天取经任务'})`,
`MATCH (master:Character {Name: 'TangSeng'}),
(student:Character {Name: 'SunWukong'}) CREATE (student)-[:MasterOf]->(master)`,
`MATCH (master:Character {Name: 'TangSeng'}),
(student:Character {Name: 'ZhuBajie'}) CREATE (student)-[:MasterOf]->(master)`,
`MATCH (master:Character {Name: 'TangSeng'}),
(student:Character {Name: 'ShaWujing'}) CREATE (student)-[:MasterOf]->(master)`,
`MATCH (companion1:Character {Name: 'SunWukong'}),
(companion2:Character {Name: 'ZhuBajie'}) CREATE (companion1)-[:CompanionOf]->(companion2)`,
`MATCH (companion1:Character {Name: 'SunWukong'}),
(companion2:Character {Name: 'ShaWujing'}) CREATE (companion1)-[:CompanionOf]->(companion2)`,
`MATCH (character:Character {Name: 'SunWukong'}),
(place:Place {Name: 'Xitian'}) CREATE (character)-[:TravelsTo]->(place)`,
`MATCH (character:Character {Name: 'ZhuBajie'}),
(place:Place {Name: 'Xitian'}) CREATE (character)-[:TravelsTo]->(place)`,
`MATCH (character:Character {Name: 'ShaWujing'}),
(place:Place {Name: 'Xitian'}) CREATE (character)-[:TravelsTo]->(place)`,
`MATCH (place:Place {Name: 'Xitian'}),
(task:Task {Name: 'Journey'}) CREATE (task)-[:MissionTo]->(place)`,
}
// 执行CQL命令
for _, query := range data {
result, err := session.Run(query, nil)
if err != nil {
log.Fatal(err)
}
// 输出查询结果
fmt.Printf("Result: %+v\n", result)
}
}
MATCH (n:Character {Name:"ZhuBajie"}),(m:Character {Name:"ShaWujing"}) Create (n)-[r:同事]->(m) return n.Name,type(r),m.Name
执行成功后,关系图谱增加了一条关系,当执行两次后,关系图谱会增加两条相同的关系:
MATCH (n:Character {Name:"ZhuBajie"})-[relation:同事]->()
WITH relation LIMIT 1
DELETE relation
MATCH (n:Character{Name:"SunWukong"})-[r]->(m) delete r return Type(r)
MATCH (n:Character{Name:"SunWukong"}) Delete (n)
Master
,猪八戒作为它的同事
,新的节点及关系添加的具体命令如下:CREATE (tang:Character {NodeID: 6, Name: '六耳猕猴', Title: '六耳猕猴'})
MATCH (master:Character {Name: 'TangSeng'}),
(student:Character {Name: '六耳猕猴'}) CREATE (student)-[:MasterOf]->(master)
MATCH (companion1:Character {Name: '六耳猕猴'}),
(companion2:Character {Name: 'ZhuBajie'}) CREATE (companion1)-[:CompanionOf]->(companion2)
执行完成后新的团队组织关系如下:
总结:以上是Neo4j的简单增删改查,对于熟练掌握Neo4j数据库来说还有很长的路要走和分析,后续需要在项目中不断学习和锤炼自己。