准备开发一个任务调度系统,其中使用Neo4j来保存和查询任务之间的依赖关系,
整理了一个服务类,记录一下。
使用的Neo4j版本为:2.1.3
服务类:
import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.factory.GraphDatabaseFactory; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.traversal.Evaluators; import org.neo4j.graphdb.traversal.PathEvaluator; import org.neo4j.graphdb.traversal.TraversalDescription; import org.neo4j.graphdb.traversal.Traverser; import org.neo4j.kernel.impl.util.FileUtils; /** * Neo4j服务类 * @author lxw * */ public class Neo4jService implements Runnable { private static Logger log = Logger.getLogger(Neo4jService.class); private final String DB_PATH = "neo4jdb/skynet-neo4j.db"; private GraphDatabaseService db; private Index<Node> index = null; public static final String INDEX_ID_KEY = "idx_id"; public static final String JOB_ID_KEY = "job_id"; private boolean running = true; private enum RelTypes implements RelationshipType{ KNOWS, } public Neo4jService() { init(); } public void init() { clearDB(); db = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH); registerShutdownHook(); Transaction tx = db.beginTx(); try { this.index = db.index().forNodes("jobNodes"); tx.success(); } catch (Exception e) { log.error(e); log.error("init() error.."); } finally { tx.close(); } } //添加节点 public boolean addNode(int job_id) { Transaction tx = db.beginTx(); try { Node jobNode = db.createNode(); jobNode.setProperty(JOB_ID_KEY, job_id); this.index.add(jobNode, INDEX_ID_KEY, job_id); tx.success(); log.info("addNode: [" + job_id + "]."); } catch (Exception e) { log.error(e); log.error("addNode() error .."); return false; } finally { tx.close(); } return true; } /** * 删除节点依赖 * @param parent_job_id * @param son_job_id * @return */ public boolean deleteNodeRelationShip(int parent_job_id,int son_job_id) { Transaction tx = db.beginTx(); try { Node parentJobNode = getNodeByJob(parent_job_id); Node sonJobNode = getNodeByJob(son_job_id); Iterable<Relationship> relationships = parentJobNode.getRelationships(RelTypes.KNOWS, Direction.OUTGOING); for(Relationship r : relationships) { if(r.getEndNode().equals(sonJobNode)) { r.delete(); } } tx.success(); log.info("deleteNodeRelationShip: [" + parent_job_id + "," + son_job_id + "]."); } catch (Exception e) { log.error(e); log.error("deleteNodeRelationShip() error .. paren_job_id is [" + parent_job_id + "], son_job_id is [" + son_job_id + "]."); } finally { tx.close(); } return false; } //删除节点 public boolean deleteNode(int job_id) { Transaction tx = db.beginTx(); try { Node jobNode = getNodeByJob(job_id); jobNode.delete(); tx.success(); log.info("deleteNode: [" + job_id + "]."); } catch (Exception e) { log.error(e); log.error("deleteNode() error .."); return false; } finally { tx.close(); } return true; } //添加节点依赖 public boolean addNodeRelationShip(int parent_job_id,int son_job_id) { Transaction tx = db.beginTx(); try { Node parentJobNode = getNodeByJob(parent_job_id); Node sonJobNode = getNodeByJob(son_job_id); parentJobNode.createRelationshipTo(sonJobNode, RelTypes.KNOWS); tx.success(); log.info("addNodeRelationShip: [" + parent_job_id + "," + son_job_id + "]."); } catch (Exception e) { log.error(e); log.error("addNodeRelationShip() error .. paren_job_id is [" + parent_job_id + "], son_job_id is [" + son_job_id + "]."); } finally { tx.close(); } return false; } //获取节点的子任务,包括自身 public List<Integer> getJobSons (int job_id,int depth) { List<Integer> jobSons = new ArrayList<Integer>(); PathEvaluator<?> path = null; if(depth == 0 || depth == -1) { path = Evaluators.excludeStartPosition(); } else { path = Evaluators.toDepth(depth); } Node jobNode = getNodeByJob(job_id); if(null != jobNode) { Transaction tx = db.beginTx(); try { TraversalDescription td = db.traversalDescription() .breadthFirst() .relationships( RelTypes.KNOWS, Direction.OUTGOING ) .evaluator(path); Traverser t = td.traverse(jobNode); for(Path p : t) { log.info("level:" + p.length()); log.info("id:" + p.endNode().getProperty(JOB_ID_KEY)); jobSons.add((Integer) p.endNode().getProperty(JOB_ID_KEY)); } tx.success(); } catch (Exception e) { log.error(e); log.error("getJobSons error .. job_id is [" + job_id + "]"); } finally { tx.close(); } } return jobSons; } //获取节点的父任务,包括自身 public List<Integer> getJobParents (int job_id,int depth) { List<Integer> jobParents = new ArrayList<Integer>(); PathEvaluator<?> path = null; if(depth == 0 || depth == -1) { path = Evaluators.excludeStartPosition(); } else { path = Evaluators.toDepth(depth); } Node jobNode = getNodeByJob(job_id); if(null != jobNode) { Transaction tx = db.beginTx(); try { TraversalDescription td = db.traversalDescription() .breadthFirst() .relationships( RelTypes.KNOWS, Direction.INCOMING ) .evaluator(path); Traverser t = td.traverse(jobNode); for(Path p : t) { log.info("level:" + p.length()); log.info("id:" + p.endNode().getProperty(JOB_ID_KEY)); jobParents.add((Integer) p.endNode().getProperty(JOB_ID_KEY)); } tx.success(); } catch (Exception e) { log.error(e); log.error("getJobParents error .. job_id is [" + job_id + "]"); } finally { tx.close(); } } return jobParents; } //获取节点的一级父任务,不包括自身 public List<Integer> getJobFirstParents (int job_id) { List<Integer> jobParents = new ArrayList<Integer>(); PathEvaluator<?> path = Evaluators.atDepth(1); Node jobNode = getNodeByJob(job_id); if(null != jobNode) { Transaction tx = db.beginTx(); try { TraversalDescription td = db.traversalDescription() .breadthFirst() .relationships( RelTypes.KNOWS, Direction.INCOMING ) .evaluator(path); Traverser t = td.traverse(jobNode); for(Path p : t) { log.info("level:" + p.length()); log.info("id:" + p.endNode().getProperty(JOB_ID_KEY)); jobParents.add((Integer) p.endNode().getProperty(JOB_ID_KEY)); } tx.success(); } catch (Exception e) { log.error(e); log.error("getJobFirstParents error .. job_id is [" + job_id + "]"); } finally { tx.close(); } } return jobParents; } //获取节点的一级子任务,不包括自身 public List<Integer> getJobFirstSons (int job_id) { List<Integer> jobSons = new ArrayList<Integer>(); PathEvaluator<?> path = Evaluators.atDepth(1); Node jobNode = getNodeByJob(job_id); if(null != jobNode) { Transaction tx = db.beginTx(); try { TraversalDescription td = db.traversalDescription() .breadthFirst() .relationships( RelTypes.KNOWS, Direction.OUTGOING ) .evaluator(path); Traverser t = td.traverse(jobNode); for(Path p : t) { log.info("level:" + p.length()); log.info("id:" + p.endNode().getProperty(JOB_ID_KEY)); jobSons.add((Integer) p.endNode().getProperty(JOB_ID_KEY)); } tx.success(); } catch (Exception e) { log.error(e); log.error("getJobFirstParents error .. job_id is [" + job_id + "]"); } finally { tx.close(); } } return jobSons; } //根据job_id获取Node public Node getNodeByJob(int job_id) { Node node = null; Transaction tx = db.beginTx(); try { node = this.index.get(INDEX_ID_KEY,job_id).getSingle(); tx.success(); } catch (Exception e) { log.error(e); log.error("getNodeByJob() error, job_id is [" + job_id + "]."); } finally { tx.close(); } return node; } private void registerShutdownHook() { // Registers a shutdown hook for the Neo4j instance so that it // shuts down nicely when the VM exits (even if you "Ctrl-C" the // running example before it's completed) Runtime.getRuntime() .addShutdownHook( new Thread() { @Override public void run() { log.info("neo4j shutdown hook ... "); db.shutdown(); } } ); } private void clearDB() { try { FileUtils.deleteRecursively(new File(DB_PATH)); } catch(IOException e) { throw new RuntimeException(e); } } @Override public void run() { while (running) { log.info(new Date() + " ### Neo4jService 运行正常!"); try { Thread.sleep(20000); } catch (InterruptedException e) { log.error(e); } } } public void setRunning(boolean running) { this.running = running; } }
测试类:
import java.util.List; public class TestNeo4j { public static void main(String[] args) { Neo4jService nj = new Neo4jService(); Thread t = new Thread(nj,"Neo4jThread"); t.start(); nj.addNode(0); nj.addNode(1); nj.addNode(2); nj.addNode(3); nj.addNode(4); nj.addNode(5); nj.addNode(6); nj.addNode(7); nj.addNode(8); nj.addNode(9); nj.addNode(10); nj.addNodeRelationShip(0,1); nj.addNodeRelationShip(0,2); nj.addNodeRelationShip(0,3); nj.addNodeRelationShip(1,4); nj.addNodeRelationShip(1,5); nj.addNodeRelationShip(1,6); nj.addNodeRelationShip(2,7); nj.addNodeRelationShip(2,9); nj.addNodeRelationShip(3,8); nj.addNodeRelationShip(3,10); nj.addNodeRelationShip(8,9); nj.addNodeRelationShip(10,9); List<Integer> sons = nj.getJobFirstParents(9); for(Integer i : sons) { System.out.println(i); } nj.deleteNodeRelationShip(2, 9); sons = nj.getJobFirstParents(9); System.out.println("after delete 2--9"); for(Integer i : sons) { System.out.println(i); } nj.setRunning(false); } }
任务的依赖关系如图:
测试输出:
14/09/11 15:39:03 INFO neo4j.Neo4jService: Thu Sep 11 15:39:03 CST 2014 ### Neo4jService 运行正常! 14/09/11 15:39:03 INFO neo4j.Neo4jService: addNode: [0]. 14/09/11 15:39:03 INFO neo4j.Neo4jService: addNode: [1]. 14/09/11 15:39:03 INFO neo4j.Neo4jService: addNode: [2]. 14/09/11 15:39:03 INFO neo4j.Neo4jService: addNode: [3]. 14/09/11 15:39:03 INFO neo4j.Neo4jService: addNode: [4]. 14/09/11 15:39:03 INFO neo4j.Neo4jService: addNode: [5]. 14/09/11 15:39:03 INFO neo4j.Neo4jService: addNode: [6]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNode: [7]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNode: [8]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNode: [9]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNode: [10]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [0,1]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [0,2]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [0,3]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [1,4]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [1,5]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [1,6]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [2,7]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [2,9]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [3,8]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [3,10]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [8,9]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: addNodeRelationShip: [10,9]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: level:1 14/09/11 15:39:04 INFO neo4j.Neo4jService: id:2 14/09/11 15:39:04 INFO neo4j.Neo4jService: level:1 14/09/11 15:39:04 INFO neo4j.Neo4jService: id:8 14/09/11 15:39:04 INFO neo4j.Neo4jService: level:1 14/09/11 15:39:04 INFO neo4j.Neo4jService: id:10 2 8 10 14/09/11 15:39:04 INFO neo4j.Neo4jService: deleteNodeRelationShip: [2,9]. 14/09/11 15:39:04 INFO neo4j.Neo4jService: level:1 14/09/11 15:39:04 INFO neo4j.Neo4jService: id:10 14/09/11 15:39:04 INFO neo4j.Neo4jService: level:1 14/09/11 15:39:04 INFO neo4j.Neo4jService: id:8 after delete 2--9 10 8 14/09/11 15:39:23 INFO neo4j.Neo4jService: neo4j shutdown hook ...
相关推荐
**Neo4j中文使用手册及例子** Neo4j是一款强大的图形数据库系统,它以其高效、灵活和直观的数据模型——图数据模型,深受开发者喜爱。在处理复杂的关系数据时,如社交网络、推荐系统、知识图谱等场景,Neo4j表现...
"Neo4j中文使用手册以及例子.7z"这个压缩包显然包含了关于如何使用Neo4j的详细指导和实例,这对于开发者来说是一份非常宝贵的资源。 1. **图形数据库基础**:首先,了解图形数据库的基本概念是必要的。与传统的关系...
在这个例子中,我们将探讨如何在Java应用中使用MyBatis与Neo4j进行集成。 首先,我们需要下载必要的jar包。MyBatis本身以及 Neo4j JDBC 驱动是实现这个集成的关键组件。通过Maven,我们可以方便地把这些依赖添加到...
- **API调用示例**:提供了如何使用这些API的实际例子。 #### 三、技术细节 **1. 性能优化** - **调优指南**:讲解如何调整配置以提高Neo4j的性能。 - **基准测试**:介绍如何进行性能测试以评估优化效果。 **2....
### Neo4j中文使用手册及实例解析 #### I. 简介 ##### 1. Neo4j的亮点 Neo4j是一款强大的图数据库系统,以其高性能和灵活性著称。其核心亮点包括: - **完整的ACID支持**:Neo4j提供完全的事务支持,确保在事务...
本文档主要讲述的是Neo4j中文使用手册以及例子;作为一款强健的,可伸缩的高性能数据库,Neo4j最适合完整的企业部署或者用于一个轻量级项目中完整服务器的一个子集存在。 适当的ACID操作是保证数据一致性的基础。...
### Neo4j中文使用手册及...通过以上内容可以看出,《Neo4j中文使用手册以及例子》全面覆盖了Neo4j的各个方面,不仅适合初学者入门,也适合高级用户深入学习。无论是理论知识还是实践技巧,都能够从中获得有益的信息。
这个例子展示了如何利用Spring Data Neo4j在Spring框架下进行数据存取操作。 首先,让我们深入了解Spring Data Neo4j的基本概念。Spring Data Neo4j通过自动映射实体类到图数据库节点,以及关系类型到图中的边,...
在Java开发中,Spring Data是一个强大的框架,它简化了数据访问层的实现,支持多种数据库技术,如JPA(Java Persistence API)、MongoDB、Neo4j和Redis。本压缩包包含的是一个使用Spring Data与这些数据库系统交互的...
通过学习Neo4j官方手册,用户可以掌握如何使用Neo4j进行数据存储、查询和图遍历,并能利用Cypher语言编写高效的查询语句,以应对复杂的数据关系和模式匹配需求。对于初学者而言,熟悉E-R图(实体-关系图)可以帮助...
- **示例**:包含了一些实际的例子,帮助理解如何使用Spring Data Neo4j。 - **配置**:描述了Spring Data Neo4j的配置选项,包括Driver Configuration等。 #### 十六、连接到Neo4j - **连接设置**:提供了如何...
由于现在网上已有的d3+neo4j的整合资源少之又少,个人大致了解了下很多代码代码例子都是用的测试例子展示而已,甚至有的网上平台的一个学习资源视频就卖到六七百块,在这里先上一个简单demo,实现的是从图数据库查询...
1. **新建**:使用Cypher语句创建节点和关系,如创建电影、演员等实体,并建立ACTED_IN关系。 2. **查找**:通过Cypher查询特定的电影和演员信息。 3. **查询**:发现演员和导演之间的关联,例如,找到共同参与电影...
- 使用`neo4j-admin import`命令直接导入CSV数据,或者 - 使用`cypher-shell`或`neo4j-console`来执行`import_csv.cypher`中的Cypher脚本。 4. 数据模型构建: 在这个例子中,可以想象一个复杂的业务网络,其中...
附件中的代码是通过spring boot框架,使用http的连接方式,对图数据库neo4j的读写操作。经过找了大量例子代码,查阅了大量的博客,各种碰壁,各种调试,终于捣鼓出来一个可以正常运行的示例代码,希望对用这个技术的...
通过具体的例子展示了如何有效地使用 Neo4j 进行数据建模。这有助于读者理解如何将实际问题映射到图数据库中。 **语言/远程客户端库** 列举了支持 Neo4j 的各种编程语言(如 Java、Python 等)及其相应的客户端库...
在2.0.2这个版本中,它可能包含了各种使用场景的示例代码,帮助开发者了解如何与Neo4j交互,执行查询、创建节点、建立关系等操作。这些例子通常会用到Cypher查询语言,这是一种专为图形数据库设计的声明式语言。 ...
例子 const Neo4JDB = require ( 'neo4j-schema' ) ; const Query = Neo4JDB . Query ; const db = new Neo4JDB ( { uri : 'bolt://localhost' , username : 'neo4j' , password : 'neo4j' } ) . connect ( ) ; ...