neo4j简单学习

背景

最近在一些论坛或者新闻里看到了neo4j,一种擅长处理图形的数据库。 据说非常适合做一些join关系型的查询,所以抽空也看了下相关文档,给自己做个技术储备。

 

过程

深入学习之前,先在网上找了一下别人的一个学习文档总结,踩在别人的肩膀上总是最快,最有效的学习。

 

顺着这些思路,逐步查看一些neo4j的相关wiki文档,摘录了一张图: 

neo4j的基本模型图: 


针对图中的一些基本概念: 

  • node : 节点
  • relationships : 关系,也就是图中的边,注意是有向边
  • properties : 属性,针对node/relationship都可以设置property
  • Traversal :  图遍历工具
  • Indexes :  索引

通过node和relationship就可以组成一个有向图,通过property就可以使其带上对应的数据,成为对应的图像数据库。

node(节点)

  1. 每个节点可以和多个节点之间建立多个关系(relationship)
  2. 单个节点可以设置多个(Key,Value)的properties属性的键值对

relationships(关系)

  1. 每个关系都会包含一个startNode和endNode
  2. 每个关系可以设置多个(Key,Value)的properties属性的键值对
  3. 可以为关系定义对应的关系类型(RelationshipType)
    *  DynamicRelationshipType 动态关系类型
    *  XXXRelationshipType 静态关系类型(实现了RelationshipType接口)

Traversal(遍历)

traverser :  http://wiki.neo4j.org/content/Traversal

一个例子: 

1.Traverser trav = swedenNode.traverse(Order.DEPTH_FIRST, StopEvaluator.END_OF_GRAPH,
2.    new ReturnableEvaluator()
3.    {
4.        public boolean isReturnableNode( TraversalPosition pos )
5.        {
6.            return !pos.isStartNode() && pos.lastRelationshipTraversed().isType( CUSTOMER_TO_ORDER );
7.        }
8.    },
9.    LIVES_IN, Direction.INCOMING,
10.    CUSTOMER_TO_ORDER, Direction.OUTGOING );
11.// iterate over traverser...<span style="white-space: normal;">
12.</span>

Order : 对应的图的遍历算法

 

  • DEPTH_FIRST :  深度优先搜索,就是找到第一个节点,递归的一直往下找,直到找不到合适的节点后,才进行回溯
  • BREADTH_FIRST :  广度优先搜索

Direction :对应图中edge的方向

  • OUTGOING : 出边
  • INCOMING : 入边
  • BOTH : 顾明思议

StopEvaluator : 定义图搜索的停止条件,默认有两个

  • DEPTH_ONE :  深度超过1后停止
  • END_OF_GRAPH :  无合适结果和停止

ReturnableEvaluator : 结果处理器,可以设置对应的返回结果,默认有:

  • ALL_BUT_START_NODE :  排除初始节点
  • ALL : 返回所有节点

TraversalPosition : 对应搜索过程中的node节点信息,包括:

  • 上一个节点信息
  • 上一个进入的Relationship信息
  • 搜索深度
  • 目前为止满足条件的节点数

Indexs(索引)

neo4j中针对每个node/relationship/property都是进行独立存储,都是按照自然的顺序。为了支持一些场景,比如针对关系型数据库的根据主键name查询对应的person node,普通的Traversal很难满足这样的需求,而且人家也不是用来解决这个事的。所以neo4j就引出了一个index的概念。 

 

早期的版本的index是采用了IndexService(http://wiki.neo4j.org/content/Indexing_with_IndexService)

一个例子:

1.GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "path/to/neo4j-db" );
2.IndexService index = new LuceneIndexService( graphDb );
3.
4.Node andy = graphDb.createNode();
5.Node larry = graphDb.createNode();
6.
7.andy.setProperty( "name", "Andy Wachowski" );
8.andy.setProperty( "title", "Director" );
9.larry.setProperty( "name", "Larry Wachowski" );
10.larry.setProperty( "title", "Director" );
11.index.index( andy, "name", andy.getProperty( "name" ) );
12.index.index( andy, "title", andy.getProperty( "title" ) );
13.index.index( larry, "name", larry.getProperty( "name" ) );
14.index.index( larry, "title", larry.getProperty( "title" ) );

IndexService是做为外部的component进行扩展定义。 

 

现在官方文档中是建议使用Integrated Index Framework

 

  1. 官方文档: http://docs.neo4j.org/chunked/stable/indexing.html
  2. 迁移方案: http://wiki.neo4j.org/content/Transitioning_To_Index_Framework

新版本例子: 

1.IndexManager index = graphDb.index();
2.Index<Node> actors = index.forNodes( "actors" );
3.Index<Node> movies = index.forNodes( "movies" );
4.RelationshipIndex roles = index.forRelationships( "roles" );

从新版本中,已经将index做为其内核的实现,并不是外部扩展包的机制,从而可见其重要性阿,想了解具体的内容可以详细看下对应的官方文档。

查询语法(Cyphe Query Language)

neo4j自己基于图论的搜索算法,实现了一套查询语言解析,提供了一些常见的聚合函数(max,sum,min,count等)。

 

语法例子:

1.Join查询:
2.start n=(1) match (n)-[:BLOCKS]->(x) return x
3.
4.Where条件:
5.start n=(2, 1) where (n.age < 30 and n.name = "Tobias") or not(n.name = "Tobias") return n
6.
7.聚合函数:
8.start n=(2,3,4) return avg(n.property)
9.
10.Order:
11.start n=(1,2,3) return n order by n.name DESC
12.
13.分页:
14.start n=(1,2,3,4,5) return n order by n.name skip 1 limit 2

调用例子:

1.db = new ImpermanentGraphDatabase();
2.engine = new ExecutionEngine( db );
3.CypherParser parser = new CypherParser();
4.ExecutionEngine engine = new ExecutionEngine(db);
5.Query query = parser.parse( "start n=(0) where 1=1 return n" );
6.ExecutionResult result = engine.execute( query );
7.assertThat( result.columns(), hasItem( "n" ) );
8.Iterator<Node> n_column = result.columnAs( "n" );
9.assertThat( asIterable( n_column ), hasItem(db.getNodeById(0)) );
10.assertThat( result.toString(), containsString("Node[0]") );

其他

现在用nosql,除了一些功能feature问题,很重要的会是关注其他的两点扩展性&可用性

扩展性

暂时未看到有相应的扩展性方案

可用性(HA机制)

目前neo4j支持简单的ha机制,是通过zookeeper进行管理。

 

它的工作机制还是挺简单的,就是由zookeeper负责neo4j server的心跳检测。

1. 发现master挂了后,会发起一个选举(没看过源码,估摸着选举的实现也会很简单,根据对应的serverid,取最小的id做为新的master)。

2. 将新的master广播给所有的slave,此时在选举过程中,不接受对应的write请求(全都是返回异常)
3. 新机器加入集群后,会做为slave于master进行通讯,同步两者的数据内容(如果当前slave的tid比master新,会产生一个数据冲突此时需要进行手工干预)

 

存在的问题:

1. zookeeper心跳检测的及时性,默认为3分钟延迟(因为会有包重试)

2. master选举期间,write请求不可处理,直接返回异常(虽然master的选举时间会相对比较端,但对客户端不够友好)

 

可以改进的点:

1. 提供客户端的api,提供一种failover重试的机制控制。

Console页面

neo4j支持嵌入式和独立部署的两种模式,部署了一下neo4j独立部署server,效果图如下:

 

图形管理后台,可以方面查看节点之间的relationships

 

 

rest接口的api,提供了图形和纯数据的几种方式:

时间: 2024-09-19 09:00:32

neo4j简单学习的相关文章

hung_task_timeout_secs 简单学习

[原文链接] http://hi.baidu.com/stealth_space/item/2007d93fe93ca28fb711dbac 接上篇 简单学习了解下 hung_task_timeout_secs 相关知识. OS: 2.6.18-194.32.1.el5 x86_64 # 先从系统中看下 hung_task 相关的参数及其参数值 [sina@localhost ~]$ sudo sysctl -a | grep hung kernel.hung_task_warnings = 0

SQL Server中的锁的简单学习

原文:SQL Server中的锁的简单学习 简介     在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的.这些查询并不会像绅士那样排队等待执行,而是会找最短的路径执行.因此,就像十字路口需要一个红绿灯那样,SQL Server也需要一个红绿灯来告诉查询:什么时候走,什么时候不可以走.这个红绿灯就是锁.     图1.查询可不会像绅士们那样按照次序进行

使用Promise解决多层异步调用的简单学习心得_javascript技巧

前言 第一次接触到Promise这个东西,是2012年微软发布Windows8操作系统后抱着作死好奇的心态研究用html5写Metro应用的时候.当时配合html5提供的WinJS库里面的异步接口全都是Promise形式,这对那时候刚刚毕业一点javascript基础都没有的我而言简直就是天书.我当时想的是,微软又在脑洞大开的瞎捣鼓了. 结果没想到,到了2015年,Promise居然写进ES6标准里面了.而且一项调查显示,js程序员们用这玩意用的还挺high. 讽刺的是,作为早在2012年就在M

Android编程之View简单学习示例_Android

本文实例讲述了Android编程之View简单学习示例.分享给大家供大家参考,具体如下: View,是Android的一个超类,这个类几乎包含了所有的屏幕类型.每一个View都有一个用于绘图的画布,这个画布可以进行任意扩展. 在游戏开发中叶可以自定义视图(View),这个画布的功能更能满足我们在游戏开发中的需要.在Android中,任何一个View类都只需重写onDraw 方法来实现界面显示,自定义的视图可以是复杂的3D实现,也可以是非常简单的文本形式等. 游戏的核心是不断地绘图和刷新界面,An

简单学习Android TextView

本文为大家分享了TextView的简单学习资料,供大家参考,具体内容如下 XML的几个特殊属性 android:autoLink 用于指定是否将文本转换成可点击的超链接形式,它的属性值有none,web,email,phone,map或all android:drawBottom 用于将图片添加到文本的低端 同理还有上,左,右 android:hint 当文本为空时,默认显示的是什么 android:Grivaity 文本的对齐方式 android:inputType 显示的文本类型 Maina

Android编程之View简单学习示例

本文实例讲述了Android编程之View简单学习示例.分享给大家供大家参考,具体如下: View,是Android的一个超类,这个类几乎包含了所有的屏幕类型.每一个View都有一个用于绘图的画布,这个画布可以进行任意扩展. 在游戏开发中叶可以自定义视图(View),这个画布的功能更能满足我们在游戏开发中的需要.在Android中,任何一个View类都只需重写onDraw 方法来实现界面显示,自定义的视图可以是复杂的3D实现,也可以是非常简单的文本形式等. 游戏的核心是不断地绘图和刷新界面,An

jmx的简单学习

背景 前段时间在看btrace源码和jdk一些源码的时候,经常会看到一些jmx的相关内容.以前对jmx基本是一片空白区,花了点时间学习记录下.   过程 jmx总体架构图:  说明:  1.  Agent : javax.management.MBeanServer实现了Agent的功能,以标准的方式给出了管理系统访问 JMX 框架的接口 2. SubAgent: javax.management.MBeans实现了SubAgent的功能,以标准的方式给出了 JMX 框架访问资源的接口 MBea

简单学习vue指令directive_javascript技巧

本文为大家分享了vue指令directive的使用方法,供大家参考,具体内容如下 1.指令的注册 指令跟组件一样需要注册才能使用,同样有两种方式,一种是全局注册: Vue.directive('dirName',function(){ //定义指令 }); 另外一种是局部注册: new Vue({ directives:{ dirName:{ //定义指令 } } }); 2.指令的定义 指令定义,官方提供了五个钩子函数来供我们使用,分别代表了一个组件的各个生命周期 bind: 只调用一次,指令

.NET分页控件简单学习_实用技巧

这几天无意间看到一个关于分页的帖子,觉得写得挺好的.关于这些东西,自己一直都是只知道原理,却没有真正动手做过,于是研究了一下分页的原理自己动手写了一个十分特别非常简单的分页程序,在这里与大家分享一下.  这个程序取数据使用的ado.net,首先先新建一个取数据的类PageDAl  using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.D