赞
踩
最近在一些论坛或者新闻里看到了neo4j,一种擅长处理图形的数据库。 据说非常适合做一些join关系型的查询,所以抽空也看了下相关文档,给自己做个技术储备。
深入学习之前,先在网上找了一下别人的一个学习文档总结,踩在别人的肩膀上总是最快,最有效的学习。
traverser : http://wiki.neo4j.org/content/Traversal
一个例子:
- Traverser trav = swedenNode.traverse(Order.DEPTH_FIRST, StopEvaluator.END_OF_GRAPH,
- new ReturnableEvaluator()
- {
- public boolean isReturnableNode( TraversalPosition pos )
- {
- return !pos.isStartNode() && pos.lastRelationshipTraversed().isType( CUSTOMER_TO_ORDER );
- }
- },
- LIVES_IN, Direction.INCOMING,
- CUSTOMER_TO_ORDER, Direction.OUTGOING );
- // iterate over traverser...
Order : 对应的图的遍历算法
neo4j中针对每个node/relationship/property都是进行独立存储,都是按照自然的顺序。为了支持一些场景,比如针对关系型数据库的根据主键name查询对应的person node,普通的Traversal很难满足这样的需求,而且人家也不是用来解决这个事的。所以neo4j就引出了一个index的概念。
早期的版本的index是采用了IndexService(http://wiki.neo4j.org/content/Indexing_with_IndexService)
一个例子:
- GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "path/to/neo4j-db" );
- IndexService index = new LuceneIndexService( graphDb );
-
- Node andy = graphDb.createNode();
- Node larry = graphDb.createNode();
-
- andy.setProperty( "name", "Andy Wachowski" );
- andy.setProperty( "title", "Director" );
- larry.setProperty( "name", "Larry Wachowski" );
- larry.setProperty( "title", "Director" );
- index.index( andy, "name", andy.getProperty( "name" ) );
- index.index( andy, "title", andy.getProperty( "title" ) );
- index.index( larry, "name", larry.getProperty( "name" ) );
- index.index( larry, "title", larry.getProperty( "title" ) );
IndexService是做为外部的component进行扩展定义。
现在官方文档中是建议使用Integrated Index Framework
- IndexManager index = graphDb.index();
- Index<Node> actors = index.forNodes( "actors" );
- Index<Node> movies = index.forNodes( "movies" );
- RelationshipIndex roles = index.forRelationships( "roles" );
neo4j自己基于图论的搜索算法,实现了一套查询语言解析,提供了一些常见的聚合函数(max,sum,min,count等)。
语法例子:
- Join查询:
- start n=(1) match (n)-[:BLOCKS]->(x) return x
-
- Where条件:
- start n=(2, 1) where (n.age < 30 and n.name = "Tobias") or not(n.name = "Tobias") return n
-
- 聚合函数:
- start n=(2,3,4) return avg(n.property)
-
- Order:
- start n=(1,2,3) return n order by n.name DESC
-
- 分页:
- start n=(1,2,3,4,5) return n order by n.name skip 1 limit 2
调用例子:
- db = new ImpermanentGraphDatabase();
- engine = new ExecutionEngine( db );
- CypherParser parser = new CypherParser();
- ExecutionEngine engine = new ExecutionEngine(db);
- Query query = parser.parse( "start n=(0) where 1=1 return n" );
- ExecutionResult result = engine.execute( query );
- assertThat( result.columns(), hasItem( "n" ) );
- Iterator<Node> n_column = result.columnAs( "n" );
- assertThat( asIterable( n_column ), hasItem(db.getNodeById(0)) );
- assertThat( result.toString(), containsString("Node[0]") );
暂时未看到有相应的扩展性方案
目前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重试的机制控制。
neo4j支持嵌入式和独立部署的两种模式,部署了一下neo4j独立部署server,效果图如下:
图形管理后台,可以方面查看节点之间的relationships
rest接口的api,提供了图形和纯数据的几种方式:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。