玩 GraphX 的时候知道了 GraphFrames ,玩 GraphFrames 的时候知道了 Cypher ,于是入坑 Neo4j。
Neo4j的安装和开发环境的搭建
https://neo4j.com/download/other-releases/,从上述链接选择合适的版本下载即可。
上述链接仅供参考。由于不同版本之间存在差异,细节上会有些许不同。(the devil is in the details.)
笔者的安装环境:
Windows7 64
jdk-8u144-windows-x64.exe
neo4j-community-3.2.6-windows.zip
可以参考 这里 搭建开发环境。当然,也可以在 IDEA 的 maven 工程中添加如下依赖,就这么简单。
<!-- Neo4j dependency -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.2.6</version>
</dependency>
Neo4j 提供 JAVA API 以编程方式执行所有数据库操作。它支持两种类型的API:
1、Neo4j 原生的 Java API
2、Neo4j Cypher Java API
Neo4j 原生 Java API 是一种低级别的纯 JAVA API,用于执行数据库操作。Neo4j Cypher Java API 是简单而强大的 JAVA API,用于执行所有CQL命令以执行数据库操作。
Neo4j 原生的 Java API
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import java.io.File;
public class Neo4jNativeJavaAPI {
private static void registerShutdownHook(final GraphDatabaseService graphDB) {
// 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)
/*为了确保neo4j数据库的正确关闭,我们可以添加一个关闭钩子方法 registerShutdownHook。 *这个方法的意思就是在jvm中增加一个关闭的钩子, *当jvm关闭的时候,会执行系统中已经设置的所有通过方法addShutdownHook添加的钩子, *当系统执行完这些钩子后,jvm才会关闭。 *所以这些钩子可以在jvm关闭的时候进行内存清理、对象销毁等操作。*/
Runtime.getRuntime().addShutdownHook(
new Thread() {
public void run() {
//Shutdown the Database
System.out.println("Server is shutting down");
graphDB.shutdown();
}
}
);
}
public static void main(String[] args) {
//指定 Neo4j 存储路径
File file = new File("D:\\neo4j-community-3.2.6\\data\\databases\\graph.db");
//Create a new Object of Graph Database
GraphDatabaseService graphDB = new GraphDatabaseFactory().newEmbeddedDatabase(file);
System.out.println("Server is up and Running");
try(Transaction tx = graphDB.beginTx()){
/** * 新增User节点 * 添加Lable以区分节点类型 * 每个节点设置name属性 */
Node user1 = graphDB.createNode(MyLabels.USERS);
user1.setProperty("name", "John Johnson");
Node user2 = graphDB.createNode(MyLabels.USERS);
user2.setProperty("name", "Kate Smith");
Node user3 = graphDB.createNode(MyLabels.USERS);
user3.setProperty("name", "Jack Jeffries");
/** * 为user1添加Friend关系 * 注:Neo4j的关系是有向的箭头,正常来讲Friend关系应该是双向的, * 此处为了简单起见,将关系定义成单向的,不会影响后期的查询 */
user1.createRelationshipTo(user2,MyRelationshipTypes.IS_FRIEND_OF);
user1.createRelationshipTo(user3,MyRelationshipTypes.IS_FRIEND_OF);
/** * 新增Movie节点 * 添加Lable以区分节点类型 * 每个节点设置name属性 */
Node movie1 = graphDB.createNode(MyLabels.MOVIES);
movie1.setProperty("name", "Fargo");
Node movie2 = graphDB.createNode(MyLabels.MOVIES);
movie2.setProperty("name", "Alien");
Node movie3 = graphDB.createNode(MyLabels.MOVIES);
movie3.setProperty("name", "Heat");
/** * 为User节点和Movie节点之间添加HAS_SEEN关系, HAS_SEEN关系设置stars属性 */
Relationship relationship1 = user1.createRelationshipTo(movie1, MyRelationshipTypes.HAS_SEEN);
relationship1.setProperty("stars", 5);
Relationship relationship2 = user2.createRelationshipTo(movie3, MyRelationshipTypes.HAS_SEEN);
relationship2.setProperty("stars", 3);
Relationship relationship6 = user2.createRelationshipTo(movie2, MyRelationshipTypes.HAS_SEEN);
relationship6.setProperty("stars", 6);
Relationship relationship3 = user3.createRelationshipTo(movie1, MyRelationshipTypes.HAS_SEEN);
relationship3.setProperty("stars", 4);
Relationship relationship4 = user3.createRelationshipTo(movie2, MyRelationshipTypes.HAS_SEEN);
relationship4.setProperty("stars", 5);
tx.success();
System.out.println("Done successfully");
} catch (Exception e) {
e.printStackTrace();
} finally {
graphDB.shutdown(); //关闭数据库
}
//Register a Shutdown Hook
registerShutdownHook(graphDB);
}
}
/** * Label类型枚举类 */
enum MyLabels implements Label {
MOVIES, USERS
}
/** * 关系类型枚举类 */
enum MyRelationshipTypes implements RelationshipType {
IS_FRIEND_OF, HAS_SEEN
}
运行完毕后,在 neo4j-community-3.2.6 目录下执行
./bin/neo4j.bat console
输出如下
2017-11-01 03:24:32.585+0000 INFO ======== Neo4j 3.2.6 ========
2017-11-01 03:24:32.601+0000 INFO Starting...
2017-11-01 03:24:33.552+0000 INFO Bolt enabled on 127.0.0.1:7687.
2017-11-01 03:24:36.714+0000 INFO Started.
2017-11-01 03:24:37.571+0000 INFO Remote interface available at http://localhost:7474/
此时,在 http://localhost:7474/ 能够看到如下图
Neo4j Cypher Java API
在 Java 程序中用 Cypher 对上图进行查询
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import java.io.File;
public class Neo4jCypherJavaAPI {
public static void main(String[] args) {
//指定 Neo4j 存储路径
File file = new File("D:\\neo4j-community-3.2.6\\data\\databases\\graph.db");
//Create a new Object of Graph Database
GraphDatabaseService graphDB = new GraphDatabaseFactory().newEmbeddedDatabase(file);
System.out.println("Server is up and Running");
try(Transaction tx = graphDB.beginTx()){
//通过Cypher查询获得结果
StringBuilder sb = new StringBuilder();
sb.append("MATCH (john)-[:IS_FRIEND_OF]->(USER)-[:HAS_SEEN]->(movie) ");
sb.append("RETURN movie");
Result result = graphDB.execute(sb.toString());
//遍历结果
while(result.hasNext()){
//get("movie")和查询语句的return movie相匹配
Node movie = (Node) result.next().get("movie");
System.out.println(movie.getId() + " : " + movie.getProperty("name"));
}
tx.success();
System.out.println("Done successfully");
} catch (Exception e) {
e.printStackTrace();
} finally {
graphDB.shutdown(); //关闭数据库
}
}
}
输出如下:
Server is up and Running
8 : Alien
9 : Heat
8 : Alien
7 : Fargo
Done successfully