Neo4j简介
Neo4j简介
发表于2013年3月16日 11:52 p.m. 位于分类图数据库与图并行计算
现实中很多数据都是用图来表达的,比如社交网络中人与人的关系、地图数据、或是基因信息等等。RDBMS并不适合表达这类数据,而且由于海量数据的存在,让其显得捉襟见肘。NoSQL数据库的兴起,很好地解决了海量数据的存放问题,图数据库也是NoSQL的一个分支,相比于NoSQL中的其他分支,它很适合用来原生表达图结构的数据。
下面一张图说明,相比于其他NoSQL,图数据库存放的数据规模有所下降,但是更能够表达复杂的数据。
通常来说,一个图数据库存储的结构就如同数据结构中的图,由顶点和边组成。
Neo4j是图数据库中一个主要代表,其开源,且用Java实现。经过几年的发展,已经可以用于生产环境。其有两种运行方式,一种是服务的方式,对外提供REST接口;另外一种是嵌入式模式,数据以文件的形式存放在本地,可以直接对本地文件进行操作。
Neo4j分三个版本:社区版(community)、高级版(advanced)和企业版(enterprise)。社区版是基础,本文主要对其作出介绍,它使用的是GPLv3协议,这意味着修改和使用其代码都需要开源,但是这是建立在软件分发的基础上,如果使用Neo4j作为服务提供,而不分发软件,则不需要开源。这实际上是GPL协议本身的缺陷。高级版和企业版建立在社区版的基础上,但多出一些高级特性。高级版包括一些高级监控特性,而企业版则包括在线备份、高可用集群以及高级监控特性。要注意它们使用了AGPLv3协议,也就是说,除非获得商业授权,否则无论以何种方式修改或者使用Neo4j,都需要开源。
接下来就从Neo4j的几个主要特性出发,结合代码逐一作出介绍。它们包括:数据模型、索引、事务、遍历和查询、以及图算法。
数据模型
Neo4j被称为property graph,除了顶点(Node)和边(Relationship,其包含一个类型),还有一种重要的部分——属性。无论是顶点还是边,都可以有任意多的属性。属性的存放类似于一个hashmap,key为一个字符串,而value必须是Java基本类型、或者是基本类型数组,比如说String、int或者int[]都是合法的。
接下来本文都会围绕下图进行举例。
可以看到Thomas Anderson这个Node有age和name的property,其指向Trinity的relationship边类型为KNOWS,有age的属性。
要生成上图所示数据,首先可以定义所有边的类型:
1
2
3
4
5
6
7
import
org.neo4j.graphdb.RelationshipType;
private
static
enum
RelTypes
implements
RelationshipType {
NEO_NODE,
KNOWS,
CODED_BY
}
接下来的代码创建了起始顶点和“Thomas Anderson”顶点,并创建了它们之间的边。其余数据生成类似。
1
2
3
4
5
6
7
8
9
import
org.neo4j.graphdb.Node;
Node startNode = graphDB.createNode();
Node thomas = graphDB.createNode();
thomas.setProperty(
"name"
,
"Thomas Anderson"
);
thomas.setProperty(
"age"
,
29
);
startNode.createRelationshipTo( thomas, RelTypes.NEO_NODE );
索引
Neo4j支持索引,其内部实际上通过Lucene实现。现在可以创建一个索引叫nodes,来索引所有拥有name属性的顶点,这样我们就可以查询名字为“Thomas Anderson”的节点了。以下代码创建了这个索引,并索引了“Thomas Anderson”顶点,并通过名字得到了它。
1
2
3
4
5
6
7
8
9
import
org.neo4j.graphdb.index.Index;
Index<Node> nodeIndex = graphDB.index().forNodes(
"nodes"
);
// 将thomas顶点的name属性添加到索引
nodeIndex.add(thomas,
"name"
, thomas.getProperty(
"name"
));
// 通过thomas的name得到顶点
Node thomas = nodeIndex.get(
"name"
,
"Thomas Anderson"
).getSingle();
事务
Neo4j完整支持事务,即满足ACID性质。示例代码如下:
1
2
3
4
5
6
7
8
9
10
import
org.neo4j.graphdb.Transaction;
Transaction tx = graphDB.beginTx();
try
{
// do sth...
tx.success();
}
finally
{
tx.finish();
}
遍历和查询
遍历是图数据库中的主要查询方式,所以遍历是图数据中相当关键的一个概念。可以用两种方式来进行遍历查询:第一种是直接编写Java代码,使用Neo4j提供的traversal框架;第二种方式是使用Neo4j提供的描述型查询语言,Cypher。第一种方式例子如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import
org.neo4j.graphdb.traversal.Evaluators;
import
org.neo4j.graphdb.traversal.Traverser;
import
org.neo4j.graphdb.traversal.TraversalDescription;
import
org.neo4j.kernel.Traversal;
public
Traverser getFriends(
final
Node person) {
TraversalDescription td = Traversal.description()
// 这里是广度优先,也可以定义为深度优先遍历
.breadthFirst()
// 这里定义边类型必须为KNOWS,且必须都为出边
.relationships(RelTypes.KNOWS, Direction.OUTGOING)
// 排除开始顶点
.evaluator(Evaluators.excludeStartPosition());
return
td.traverse(person);
}
这里得到了Traverser对象后并没有立即执行遍历,而是在真正迭代结果时才进行延迟查询。以下的代码打印出一个顶点的所有朋友以及朋友的朋友。
1
2
3
4
5
6
7
8
9
10
11
12
import
org.neo4j.graphdb.Path;
public
void
printNodeFriends(Node node) {
int
friendsNumbers =
0
;
System.out.println(node.getProperty(PRIMARY_KEY) +
"'s friends:"
);
for
(Path friendPath: getFriends(node)) {
System.out.println(
"At depth "
+ friendPath.length() +
" => "
+ friendPath.endNode().getProperty(PRIMARY_KEY));
friendsNumbers++;
}
System.out.println(
"Number of friends found: "
+ friendsNumbers);
}
输出结果为:
Thomas Anderson's friends:
At depth 1 => Trinity
At depth 1 => Morpheus
At depth 2 => Cypher
At depth 3 => Agent Smith
Number of friends found: 4
关于traversal框架,请参考官方文档。
第二种方法Cypher则直观得多,它是一种描述型的语言。下面是达到同样目标的Cypher命令。
1
2
3
start n=node:nodes(name=
"Thomas Anderson"
)
match n-[:KNOWS*..]->f
return
distinct f, f.name
简单做个说明。start说明从n节点开始,它通过查询nodes索引得到。match主要用来匹配图中顶点和边的关系,这里n和f顶点之前的relationship通过方括号表达,“:KNOWS”说明了边类型,“*..”表示可以有任意多的边,如果只要求有两条,则是[:KNOWS*2]。注意到这里的箭头表示是出边方向。return返回结果,distinct去除了重复访问到的顶点。可以看到还是很直观的。
查询结果如下:
+-----------------------------------------------------------------------------------+
| f | f.name |
+-----------------------------------------------------------------------------------+
| Node[4]{name:"Morpheus",rank:"Captain",occupation:"Total badass"} | "Morpheus" |
| Node[5]{name:"Cypher",last name:"Reagan"} | "Cypher" |
| Node[6]{name:"Agent Smith",version:"1.0b",language:"C++"} | "Agent Smith" |
| Node[3]{name:"Trinity"} | "Trinity" |
+-----------------------------------------------------------------------------------+
4 rows
289 ms
不过,Cypher语言不能定义查询是按照深度优先还是广度优先遍历。Cypher更多用法,可以参考官方文档。
图算法
Neo4j实现的三种图算法:最短路径、Dijkstra算法以及A*算法。下面是最短路径算法的简单例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import
org.neo4j.graphalgo.PathFinder;
import
org.neo4j.graphalgo.GraphAlgoFactory;
public
Iterable<Path> findShortestPath(Node node1, Node node2) {
PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
Traversal.expanderForTypes(RelTypes.KNOWS, Direction.OUTGOING),
5
);
Iterable<Path> paths = finder.findAllPaths(node1, node2);
return
paths;
}
public
void
printShortestPaths() {
Node node1 = nodeIndex.get(PRIMARY_KEY,
"Thomas Anderson"
).getSingle();
Node node2 = nodeIndex.get(PRIMARY_KEY,
"Agent Smith"
).getSingle();
for
(Path shortestPath: findShortestPath(node1, node2)) {
System.out.println(shortestPath.toString());
}
}
图算法的更多信息,可以参考官方文档。
总结
本文对Neo4j做了简单的介绍,更多信息可以参考Neo4j的官方网站。
在社交网络呈爆炸性发展的今天,随着knowledge graph(知识图谱)技术的兴起,相信图数据库能够扮演越来越重要的角色。
本文使用的完整代码,可以在这里下载。
Neo4j简介的更多相关文章
- 图数据库Neo4j简介
图数据库Neo4j简介 转自: 图形数据库Neo4J简介 - loveis715 - 博客园https://www.cnblogs.com/loveis715/p/5277051.html 最近我在用 ...
- 图形数据库Neo4J简介
最近我在用图形数据库来完成对一个初创项目的支持.在使用过程中觉得这种图形数据库实际上挺有意思的.因此在这里给大家做一个简单的介绍. NoSQL数据库相信大家都听说过.它们常常可以用来处理传统的关系型数 ...
- 1.Neo4j简介(Neo4j系列)
简介 Neo4j是一个高性能.高可靠性.可扩展.支持ACID事务的图数据库,它基本由Java语言实现,支持数据平台的平滑扩展和过渡,同时能够在多种系统上完成部署,它使用Cypher查询语言对数据进行增 ...
- Neo4j 简介 2019
Neo4j是一个世界领先的开源图形数据库,由 Java 编写.图形数据库也就意味着它的数据并非保存在表或集合中,而是保存为节点以及节点之间的关系. Neo4j 的数据由下面几部分构成: 节点边属性Ne ...
- Neo4j图数据库简介和底层原理
现实中很多数据都是用图来表达的,比如社交网络中人与人的关系.地图数据.或是基因信息等等.RDBMS并不适合表达这类数据,而且由于海量数据的存在,让其显得捉襟见肘.NoSQL数据库的兴起,很好地解决了海 ...
- Cassandra简介
在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...
- Ubuntu 下 Neo4j单机安装和集群环境安装
1. Neo4j简介 Neo4j是一个用Java实现的.高性能的.NoSQL图形数据库.Neo4j 使用图(graph)相关的概念来描述数据模型,通过图中的节点和节点的关系来建模.Neo4j完全兼容A ...
- 通过Spring Data Neo4J操作您的图形数据库
在前面的一篇文章<图形数据库Neo4J简介>中,我们已经对其内部所使用的各种机制进行了简单地介绍.而在我们尝试对Neo4J进行大版本升级时,我发现网络上并没有任何成型的样例代码以及简介,而 ...
- 在Django中使用Neo4j
重要的先说在前面吧,最后的选型结构是安装了最新的neo4j版本3.0.3,使用了neo4j-rest-client客户端库.主要原因是更适用于django的neomodel库目前只支持neo4j2.2 ...
随机推荐
- 泛泰A900 刷4.4专用中文TWRP2.7.1.1版 支持自己主动识别手机版本号(全球首创)
因本人手上的A900S已砖, 所以临时弄不了ROM了, 先上传之前已经弄好的刷4.4专用的新版TWRP recovery 2.7.1.1 这个版本号是我自己定义的,为差别之前公布的2.7.0.0版( ...
- opengl笔记——旋转,一段代码的理解
重看:opengl笔记——OpenGL好资料备忘 在找到这段代码,对理解opengl旋转很有帮助 ... glPushMatrix(); // initialze ModelView matrix g ...
- javascript中关于数组的迭代方法
//都接受3个参数,分别为:值.在数组中的位置.数组对象本身 var num = [2, 1, 5, 4, 2, 1, 6, 8, 19]; //every:若每一项都返回true,则返回true v ...
- Windows计算器使用详解
(1)Backspace:退格,删除当前输入数字中的最后一位 (2)CE:清除,清除显示的数字. (3)C:归零,清除当前的计算. (4)MC:清除存储器中的数值. (5)MR:将存于存储器中的数显示 ...
- TcpClient
public class TcpClientSession { protected TcpClient Client { get; set; } /// <summary> /// 远程地 ...
- JQuery弹出层,点击按钮后弹出遮罩层,有关闭按钮
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...
- SpringMVC(三) —— 参数绑定和数据回显
参数绑定的过程:就是页面向后台传递参数,后台接受的一个过程. 默认支持的参数类型:(就是你在方法上以形参的形式去定义一下的类型,就可以直接使用它) HttpServletRequest HttpSer ...
- python基础之 sys.argv[]用法
sys.argv[]是用来获取命令行参数的,sys.argv[0]表示代码本身文件路径,所以参数从1开始. arg[1]表示第一个命令行参数 arg[1][2:] 表示取第一个命令行参数,但是去掉前两 ...
- Mongodb常见错误
1. log目录没有创建,而在logpath中有设定 2. SECONDARY默认不可以读取数据,需要db.getMongo().setSlaveOk(); 3. SECONDARY不可以写数据 4. ...
- 【11.2noip冲刺赛】 循环整数 (分段打表)
[问题描述]moreD在学习完循环小数之后发现循环是个很美好的性质.自己只需要记住短短的循环节以及循环次数(次数大于1,且是整数)就可以记住整个数字了.因为背诵数字变得方便了,moreD决定背诵[L, ...