neo4j遍历和图算法
这篇blog主要和大家分享一下neo4j中是如何对节点进行遍历,和其中集成的图论的一些常用算法。
遍历
http://docs.neo4j.org.cn/tutorials-java-embedded-traversal.html 这是neo4j官方的中文教程。
- private static Traverser getFriends(Node node )
- {
- TraversalDescription td = Traversal.description()
- .breadthFirst()
- .relationships( RelTypes.KNOWS, Direction.OUTGOING )
- .evaluator( Evaluators.excludeStartPosition() );
- return td.traverse( node );
- }
private static Traverser getFriends(Node node )
{
TraversalDescription td = Traversal.description()
.breadthFirst()
.relationships( RelTypes.KNOWS, Direction.OUTGOING )
.evaluator( Evaluators.excludeStartPosition() );
return td.traverse( node );
}
TraversalDescription提供了用户遍历节点的方法,并且用户需要自己添加遍历的条件。
- int num = 0;
- String result = neoNode.getProperty( "name" ) + "'s friends:\n";
- Traverser friendsTraverser = getFriends( neoNode );
- for ( Path friendPath : friendsTraverser )
- {
- output += "At depth " + friendPath.length() + " => "
- + friendPath.endNode()
- .getProperty( "name" ) + "\n";
- numberOfFriends++;
- }
- output += "Number of friends found: " + numberOfFriends + "\n";
int num = 0;
String result = neoNode.getProperty( "name" ) + "'s friends:\n";
Traverser friendsTraverser = getFriends( neoNode );
for ( Path friendPath : friendsTraverser )
{
output += "At depth " + friendPath.length() + " => "
+ friendPath.endNode()
.getProperty( "name" ) + "\n";
numberOfFriends++;
}
output += "Number of friends found: " + numberOfFriends + "\n";
打印出结果
- Thomas Anderson's friends:
- At depth 1 => Trinity
- At depth 1 => Morpheus
- At depth 2 => Cypher
- At depth 3 => Agent Smith
- 找到朋友的数量: 4
Thomas Anderson's friends:
At depth 1 => Trinity
At depth 1 => Morpheus
At depth 2 => Cypher
At depth 3 => Agent Smith
找到朋友的数量: 4
下面介绍如何按照一个预先定义好的顺序遍历图。
- Node A = db.createNode();
- Node B = db.createNode();
- Node C = db.createNode();
- Node D = db.createNode();
- A.createRelationshipTo( B, REL1 );
- B.createRelationshipTo( C, REL2 );
- C.createRelationshipTo( D, REL3 );
- A.createRelationshipTo( C, REL2 );
Node A = db.createNode();
Node B = db.createNode();
Node C = db.createNode();
Node D = db.createNode();
A.createRelationshipTo( B, REL1 );
B.createRelationshipTo( C, REL2 );
C.createRelationshipTo( D, REL3 );
A.createRelationshipTo( C, REL2 );
现在关系(REL1-->REL2-->REL), 当遍历的时候,Evaluator能够对它进行检验,确保只有该关系顺序的路径才会被包括。
- ArrayList<RelationshipType> orderedPathContext = new ArrayList<RelationshipType>();
- orderedPathContext.add( REL1 );
- orderedPathContext.add( withName( "REL2" ) );
- orderedPathContext.add( withName( "REL3" ) );
- TraversalDescription td = Traversal.description()
- .evaluator( new Evaluator()
- {
- @Override
- public Evaluation evaluate( final Path path )
- {
- if ( path.length() == 0 )
- {
- return Evaluation.EXCLUDE_AND_CONTINUE;
- }
- RelationshipType expectedType = orderedPathContext.get( path.length() - 1 );
- boolean isExpectedType = path.lastRelationship()
- .isType( expectedType );
- boolean included = path.length() == orderedPathContext.size()
- && isExpectedType;
- boolean continued = path.length() < orderedPathContext.size()
- && isExpectedType;
- return Evaluation.of( included, continued );
- }
- } );
ArrayList<RelationshipType> orderedPathContext = new ArrayList<RelationshipType>();
orderedPathContext.add( REL1 );
orderedPathContext.add( withName( "REL2" ) );
orderedPathContext.add( withName( "REL3" ) );
TraversalDescription td = Traversal.description()
.evaluator( new Evaluator()
{
@Override
public Evaluation evaluate( final Path path )
{
if ( path.length() == 0 )
{
return Evaluation.EXCLUDE_AND_CONTINUE;
}
RelationshipType expectedType = orderedPathContext.get( path.length() - 1 );
boolean isExpectedType = path.lastRelationship()
.isType( expectedType );
boolean included = path.length() == orderedPathContext.size()
&& isExpectedType;
boolean continued = path.length() < orderedPathContext.size()
&& isExpectedType;
return Evaluation.of( included, continued );
}
} );
打印出结果
- Traverser traverser = td.traverse( A );
- PathPrinter pathPrinter = new PathPrinter( "name" );
- for ( Path path : traverser )
- {
- output += Traversal.pathToString( path, pathPrinter );
- }
Traverser traverser = td.traverse( A );
PathPrinter pathPrinter = new PathPrinter( "name" );
for ( Path path : traverser )
{
output += Traversal.pathToString( path, pathPrinter );
}
用户也可以通过自定义格式输出路径。
- static class PathPrinter implements Traversal.PathDescriptor<Path>
- {
- private final String nodePropertyKey;
- public PathPrinter( String nodePropertyKey )
- {
- this.nodePropertyKey = nodePropertyKey;
- }
- @Override
- public String nodeRepresentation( Path path, Node node )
- {
- return "(" + node.getProperty( nodePropertyKey, "" ) + ")";
- }
- @Override
- public String relationshipRepresentation( Path path, Node from,
- Relationship relationship )
- {
- String prefix = "--", suffix = "--";
- if ( from.equals( relationship.getEndNode() ) )
- {
- prefix = "<--";
- }
- else
- {
- suffix = "-->";
- }
- return prefix + "[" + relationship.getType().name() + "]" + suffix;
- }
- }
static class PathPrinter implements Traversal.PathDescriptor<Path>
{
private final String nodePropertyKey;public PathPrinter( String nodePropertyKey )
{
this.nodePropertyKey = nodePropertyKey;
} @Override
public String nodeRepresentation( Path path, Node node )
{
return "(" + node.getProperty( nodePropertyKey, "" ) + ")";
} @Override
public String relationshipRepresentation( Path path, Node from,
Relationship relationship )
{
String prefix = "--", suffix = "--";
if ( from.equals( relationship.getEndNode() ) )
{
prefix = "<--";
}
else
{
suffix = "-->";
}
return prefix + "[" + relationship.getType().name() + "]" + suffix;
}
}
图算法
- public Iterable<Path> findShortestPath(Node node1, Node node2) {
- PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
- Traversal.expanderForTypes(RelTypes.KNOWS, Direction.BOTH), 10);
- Iterable<Path> paths = finder.findAllPaths(node1, node2);
- return paths;
- }
public Iterable<Path> findShortestPath(Node node1, Node node2) {
PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
Traversal.expanderForTypes(RelTypes.KNOWS, Direction.BOTH), 10);
Iterable<Path> paths = finder.findAllPaths(node1, node2);
return paths;
}
- for(Path shortestPath: findShortestPath(aa, ab)) {
- System.out.println(shortestPath.toString());
- }
for(Path shortestPath: findShortestPath(aa, ab)) {
System.out.println(shortestPath.toString());
}
Traversal.expanderForTypes用来定义遍历的深度和节点关系的出入度。
- PathFinder<WeightedPath> finder = GraphAlgoFactory.dijkstra(
- Traversal.expanderForTypes( ExampleTypes.MY_TYPE, Direction.BOTH ), "cost" );
- WeightedPath path = finder.findSinglePath( nodeA, nodeB );
- path.weight();
PathFinder<WeightedPath> finder = GraphAlgoFactory.dijkstra(
Traversal.expanderForTypes( ExampleTypes.MY_TYPE, Direction.BOTH ), "cost" ); WeightedPath path = finder.findSinglePath( nodeA, nodeB );
path.weight();
使用 A*算法是解决静态路网中求解最短路最有效的方法。
- Node nodeA = createNode( "name", "A", "x", 0d, "y", 0d );
- Node nodeB = createNode( "name", "B", "x", 7d, "y", 0d );
- Node nodeC = createNode( "name", "C", "x", 2d, "y", 1d );
- Relationship relAB = createRelationship( nodeA, nodeC, "length", 2d );
- Relationship relBC = createRelationship( nodeC, nodeB, "length", 3d );
- Relationship relAC = createRelationship( nodeA, nodeB, "length", 10d );
- EstimateEvaluator<Double> estimateEvaluator = new EstimateEvaluator<Double>()
- {
- public Double getCost( final Node node, final Node goal )
- {
- double dx = (Double) node.getProperty( "x" ) - (Double) goal.getProperty( "x" );
- double dy = (Double) node.getProperty( "y" ) - (Double) goal.getProperty( "y" );
- double result = Math.sqrt( Math.pow( dx, 2 ) + Math.pow( dy, 2 ) );
- return result;
- }
- };
- PathFinder<WeightedPath> astar = GraphAlgoFactory.aStar(
- Traversal.expanderForAllTypes(),
- CommonEvaluators.doubleCostEvaluator( "length" ), estimateEvaluator );
- WeightedPath path = astar.findSinglePath( nodeA, nodeB );
Node nodeA = createNode( "name", "A", "x", 0d, "y", 0d );
Node nodeB = createNode( "name", "B", "x", 7d, "y", 0d );
Node nodeC = createNode( "name", "C", "x", 2d, "y", 1d );
Relationship relAB = createRelationship( nodeA, nodeC, "length", 2d );
Relationship relBC = createRelationship( nodeC, nodeB, "length", 3d );
Relationship relAC = createRelationship( nodeA, nodeB, "length", 10d ); EstimateEvaluator<Double> estimateEvaluator = new EstimateEvaluator<Double>()
{
public Double getCost( final Node node, final Node goal )
{
double dx = (Double) node.getProperty( "x" ) - (Double) goal.getProperty( "x" );
double dy = (Double) node.getProperty( "y" ) - (Double) goal.getProperty( "y" );
double result = Math.sqrt( Math.pow( dx, 2 ) + Math.pow( dy, 2 ) );
return result;
}
};
PathFinder<WeightedPath> astar = GraphAlgoFactory.aStar(
Traversal.expanderForAllTypes(),
CommonEvaluators.doubleCostEvaluator( "length" ), estimateEvaluator );
WeightedPath path = astar.findSinglePath( nodeA, nodeB );
neo4j遍历和图算法的更多相关文章
- 关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL))
关于图计算&图学习的基础知识概览:前置知识点学习(Paddle Graph Learning (PGL)) 欢迎fork本项目原始链接:关于图计算&图学习的基础知识概览:前置知识点学习 ...
- 20172305 2018-2019-1 《Java软件结构与数据结构》第九周学习总结
20172305 2018-2019-1 <Java软件结构与数据结构>第九周学习总结 教材学习内容总结 本周内容主要为书第十五章内容: 图(结点和结点之间的连接构成) 顶点:结点 边:结 ...
- CF-544:部分题目总结
-------------------昨天打的重现赛,感觉是我打的发挥的最好的一场比赛了,六题都一次AC.那么就来总结一下吧 题目链接:http://codeforces.com/contest/11 ...
- Neo4j简介
Neo4j简介 发表于2013年3月16日 11:52 p.m. 位于分类图数据库与图并行计算 现实中很多数据都是用图来表达的,比如社交网络中人与人的关系.地图数据.或是基因信息等等.RDBMS ...
- 为什么选择图形数据库,为什么选择Neo4j?
最近在抓取一些社交网站的数据,抓下来的数据用MySql存储.问我为什么用MySql,那自然是入门简单,并且我当时只熟悉MySql.可是,随着数据量越来越大,有一个问题始终困扰着我,那就是社交关系的存储 ...
- 主流图数据库Neo4J、ArangoDB、OrientDB综合对比:架构分析
主流图数据库Neo4J.ArangoDB.OrientDB综合对比:架构分析 YOTOY 关注 0.4 2017.06.15 15:11* 字数 3733 阅读 16430评论 2喜欢 18 1: 本 ...
- Neo4j
Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌入式的.基于磁盘的.具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做 ...
- 图数据库neo4j和关系数据库的区别
相信您和我一样,在使用关系型数据库时常常会遇到一系列非常复杂的设计问题.例如一部电影中的各个演员常常有主角配角之分,还要有导演,特效等人员的参与.通常情况下这些人员常常都被抽象为Person类型,对应 ...
- Neo4j图数据库管理系统开发笔记之一:Neo4j Java 工具包
1 应用开发概述 基于数据传输效率以及接口自定义等特殊性需求,我们暂时放弃使用Neo4j服务器版本,而是在Neo4j嵌入式版本的基础上进行一些封装性的开发.封装的重点,是解决Neo4j嵌入式版本Emb ...
随机推荐
- SQLite C++ Wrapper 是一个 C++ 语言对 SQLite 的最小封装包。
SQLite C++ Wrapper 是一个 C++ 语言对 SQLite 的最小封装包. 示例代码1: #include <string> #include <iostream ...
- 使用Parallel.Invoke并行你的代码
优势和劣势 使用Parallel.Invoke的优势就是使用它执行很多的方法很简单,而不用担心任务或者线程的问题.然而,它并不是适合所有的场景.Parallel.Invoke有很多的劣势 如果你使用它 ...
- 47 Majority Element II
原题网址; https://www.lintcode.com/problem/majority-element-ii/ 描述 给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的三 ...
- R语言数据预处理
R语言数据预处理 一.日期时间.字符串的处理 日期 Date: 日期类,年与日 POSIXct: 日期时间类,精确到秒,用数字表示 POSIXlt: 日期时间类,精确到秒,用列表表示 Sys.date ...
- disruptor 高效队列
disruptor 是什么: disruptor 是一个 低延时的 无锁 环形 队列. 相较于 java的 队列 ,他有明显的优点 ,无界,无锁,低延时(解决了为内存共享问题 ) disrupto ...
- Python运算符,逻辑运算
运算符 计算机可以进行的运算有很多种,可不只加减乘除这么简单,运算按种类可分为算数运算.比较运算.逻辑运算.赋值运算.成员运算.身份运算.位运算,今天我们暂只学习算数运算.比较运算.逻辑运算.赋值运算 ...
- Leetcode513. Find Bottom Left Tree Value找树左下角的值
给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输出: 7 注意: 您可以假 ...
- Mobox 知识管理平台助推市长质量奖
Mobox 知识管理平台助推市长质量奖 引言: 在过去的十多年中,国际上在管理领域出现两股浪潮:一是许多国家和地区采取设立政府质量奖的方式,来改善企业管理绩效,提升区域整体竞争力:二是这些国家和地区的 ...
- ajax发送验证码
$.ajax({ url:url, type:"POST", data:data, dataType:"JSON", s ...
- 19-10-17-T
真的T了.(滑稽 Final 35 Miemeng 100 03:12:51 0 03:12:54 15 03:12:55 115 03:12:55 幸好$T1$还能要,不然就…… 前言 中午$\sc ...