准备开发一个任务调度系统,其中使用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中文使用手册以及例子》全面覆盖了Neo4j的各个方面,不仅适合初学者入门,也适合高级用户深入学习。无论是理论知识还是实践技巧,都能够从中获得有益的信息。
这个例子展示了如何利用Spring Data Neo4j在Spring框架下进行数据存取操作。 首先,让我们深入了解Spring Data Neo4j的基本概念。Spring Data Neo4j通过自动映射实体类到图数据库节点,以及关系类型到图中的边,...
在Java开发中,Spring Data是一个强大的框架,它简化了数据访问层的实现,支持多种数据库技术,如JPA(Java Persistence API)、MongoDB、Neo4j和Redis。本压缩包包含的是一个使用Spring Data与这些数据库系统交互的...
由于现在网上已有的d3+neo4j的整合资源少之又少,个人大致了解了下很多代码代码例子都是用的测试例子展示而已,甚至有的网上平台的一个学习资源视频就卖到六七百块,在这里先上一个简单demo,实现的是从图数据库查询...
通过学习Neo4j官方手册,用户可以掌握如何使用Neo4j进行数据存储、查询和图遍历,并能利用Cypher语言编写高效的查询语句,以应对复杂的数据关系和模式匹配需求。对于初学者而言,熟悉E-R图(实体-关系图)可以帮助...
- **示例**:包含了一些实际的例子,帮助理解如何使用Spring Data Neo4j。 - **配置**:描述了Spring Data Neo4j的配置选项,包括Driver Configuration等。 #### 十六、连接到Neo4j - **连接设置**:提供了如何...
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 ( ) ; ...
egg-neo4j Neo4j用于鸡蛋框架。安装$ npm i egg-neo4j --save用法// {app_root}/config/plugin.jsexports ....例子假设我们的数据库中有User节点,我们想获取所有这些节点: async function all ( ) { con