Neo4j 是一套原生實現 (底層設計就是為了圖資料庫設計,而不是用例如一般關聯式資料庫去模擬) 圖資料庫(Graph Database) 的工具
Neo4j Community Edition 版本可以到
Neo4j 官網的下載中心 免費下載使用,
除了有啟動 Neo4j server 的功能外還提供了以網頁存取的方便介面 。
下載 Neo4j Community Edition 後,把下載下來的 zip 檔解壓縮,
進入到資料夾裡的 bin 資料夾,用命令列模式 (command line)
打上
neo4j console
指令後,可以用瀏覽器到 http://localhost:7474/browser/ 看到 UI 介面,提供各種功能,例如執行語法及可視化結果,預設登入 Database 的帳號密碼會都是 "neo4j" ,可以自行修改。
這邊紀錄下使用 Java 去讀取 Neo4j 查詢結果的方法,首先來看下需要的依賴 Maven Dependency:
<!-- https://mvnrepository.com/artifact/org.neo4j.driver/neo4j-java-driver -->
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>4.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.neo4j/neo4j-jdbc-driver -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-jdbc-driver</artifactId>
<version>4.0.4</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.neo4j/neo4j -->
<!-- neo4j embedded version -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>4.4.2</version>
</dependency>
以上三個 neo4j 的 dependency 可以擇一使用,可依你想要存取 neo4j 的方式來選擇,分述如下:
- org.neo4j.driver 的 neo4j-java-driver :
使用 Driver 的方式來存取 neo4j ,有較接近 neo4j 原生結構的類別可操作使用,
需要跟已開啟的 neo4j server 做連線,使用像例如
neo4j://localhost:7687
這樣的方式來操縱 neo4j 資料庫。 - org.neo4j 的 neo4j-jdbc-driver :
使用 JDBC 的方式來存 neo4j ,
需要跟已開啟的 neo4j server 做連線,使用像例如
jdbc:neo4j:bolt://localhost:7687?user=xxx,password=xxx,scheme=basic
的方式操縱 neo4j 資料庫。
跟 neo4j-java-driver 比起來,neo4j-jdbc-driver 沒有接近 neo4j 原生結構的類別可操作使用,
只能使用 jdbc 的 (Map) ResultSet.getObject() 方式等存取 - org.neo4j 的 neo4j :
使用 嵌入式(embedded) 的方式來存取本地端的 neo4j 資料庫檔案,
可以直接處理本地端 neo4j 資料庫檔案 (通常為一個資料夾),
不需開啟 neo4j server 做連線,適合用在無 server 的環境,
有較接近 neo4j 原生結構的類別可操作使用,
例如可直接對整個 neo4j-community-4.4.2 資料夾及指定 Database 名稱來做存取。
內容為一個英雄人物曾當過哪些英雄的關係圖,像是這個樣子:
Bruce Wayne -[hasBeenHero] -> Batman
Dick Grayson -[hasBeenHero] -> Batman
Dick Grayson -[hasBeenHero] -> Nightwing
Dick Grayson -[hasBeenHero] -> Robin
建構資料的語法如下
//create "Persion" nodes
MERGE (bruceWayne:Person {name: 'Bruce Wayne'})
MERGE (dickGrayson:Person {name: 'Dick Grayson'})
//create "Hero" nodes
WITH bruceWayne,
dickGrayson,
[
{name: 'Batman'},
{name: 'Nightwing'},
{name: 'Robin'}
] AS heros
//create and set relatoinship
FOREACH (hero in heros |
CREATE (h:Hero) SET h = hero
CREATE (dickGrayson)-[:hasBeenHero]->(h)
)
WITH bruceWayne
MATCH (batman:Hero{name:'Batman'})
CREATE (bruceWayne)-[:hasBeenHero]->(batman)用視覺化來看的話資料庫結果會如下圖:接下來我們來看看要如何用 Java 把資料庫的 Node 和 Relationship 都查出來,
以下直接上 Java 程式碼,實現了三個 method ,分別對應了上述的三種存取 neo4j Database 的方式,分別是:
queryByDriver() 對應 org.neo4j.driver 的 neo4j-java-driver
queryByJdbc() 對應 org.neo4j 的 neo4j-jdbc-driver
queryByEmbeddedMode() 對應 org.neo4j 的 neo4j
Neo4jTest.java :
package main;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.dbms.api.DatabaseManagementServiceBuilder;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Record;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Relationship;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.impl.core.NodeEntity;
import org.neo4j.kernel.impl.core.RelationshipEntity;
public class Neo4jTest {
public static void main(String... args) throws Exception {
String databaseName = "neo4j";
String userName = "neo4j";
String password = "neo4j";
String neo4jServerUrl = "localhost:7687";
Path neo4jDBHomeDirectoryPath = Paths.get(ClassLoader.getSystemResource("neo4j-community-4.4.2").toURI());
//or if the database directory is located on other path:
//Path neo4jDBHomeDirectoryPath = Paths.get("D:\\xxx\\yyy\\neo4j-community-4.4.2");
queryByDriver("neo4j://" + neo4jServerUrl, userName, password);
queryByJdbc(neo4jServerUrl, userName, password);
queryByEmbeddedMode(neo4jDBHomeDirectoryPath, databaseName);
System.out.println("Done");
}
public static void queryByDriver(String uri, String username, String password) {
try (Driver driver = GraphDatabase.driver(uri, AuthTokens.basic(username, password));
Session session = driver.session();) {
List<String> dataList = session.readTransaction(tx -> {
List<String> resultList = new ArrayList<String>();
Result result = tx.run("MATCH (person:Person)-[relationship:hasBeenHero]->(hero:Hero) "
+ "RETURN * "
+ "ORDER BY person.name, hero.name");
while(result.hasNext()) {
Record record = result.next();
Node person = record.get("person").asNode();
Relationship relationship = record.get("relationship").asRelationship();
Node hero = record.get("hero").asNode();
String resultStr = person.get("name").asString() + " -" + relationship.type() + "-> " + hero.get("name").asString();
// System.out.println(resultStr); // who -hasBeenHero-> whatHero
resultList.add(resultStr);
}
return resultList;
});
for (String data : dataList) {
System.out.println(data);
/* output:
Bruce Wayne -hasBeenHero-> Batman
Dick Grayson -hasBeenHero-> Batman
Dick Grayson -hasBeenHero-> Nightwing
Dick Grayson -hasBeenHero-> Robin
*/
}
}catch(Exception e) {
e.printStackTrace();
}
}
public static void queryByJdbc(String uri, String username, String password) {
try (Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://" + uri + "?user=" + username + ",password=" + password +",scheme=basic");
PreparedStatement pstmt = con.prepareStatement("MATCH (person:Person)-[relationship:hasBeenHero]->(hero:Hero) "
+ "RETURN * "
+ "ORDER BY person.name, hero.name");
ResultSet rs = pstmt.executeQuery();
){
while(rs.next()) {
Map person = (Map) rs.getObject("person");
Map relationship = (Map) rs.getObject("relationship");
Map hero = (Map) rs.getObject("hero");
String resultStr = person.get("name") + " -" + relationship.get("_type") + "-> " + hero.get("name");
System.out.println(resultStr);
/* output:
Bruce Wayne -hasBeenHero-> Batman
Dick Grayson -hasBeenHero-> Batman
Dick Grayson -hasBeenHero-> Nightwing
Dick Grayson -hasBeenHero-> Robin
*/
}
}catch(Exception e) {
e.printStackTrace();
}
}
// Don't need to start server manually, it will start server by itself.
// Don't need username and password.
public static void queryByEmbeddedMode(Path neo4jDBHomeDirectoryPath, String databaseName) {
DatabaseManagementService databaseManagementService = new DatabaseManagementServiceBuilder(neo4jDBHomeDirectoryPath).build();
GraphDatabaseService graphDatabaseService = databaseManagementService.database(databaseName);
// 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 application).
// Runtime.getRuntime().addShutdownHook( new Thread()
// {
// @Override
// public void run()
// {
// databaseManagementService.shutdown();
// }
// } );
try(Transaction tx = graphDatabaseService.beginTx();){
org.neo4j.graphdb.Result result = tx.execute("MATCH (person:Person)-[relationship:hasBeenHero]->(hero:Hero) "
+ "RETURN * "
+ "ORDER BY person.name, hero.name");
while(result.hasNext()) {
Map<String,Object> record = result.next();
NodeEntity person = (NodeEntity) record.get("person");
RelationshipEntity relationship = (RelationshipEntity) record.get("relationship");
NodeEntity hero = (NodeEntity) record.get("hero");
String resultStr = person.getProperty("name") + " -" + relationship.getType().name() + "-> " + hero.getProperty("name");
System.out.println(resultStr);
/* output:
Bruce Wayne -hasBeenHero-> Batman
Dick Grayson -hasBeenHero-> Batman
Dick Grayson -hasBeenHero-> Nightwing
Dick Grayson -hasBeenHero-> Robin
*/
}
}catch(Exception e) {
e.printStackTrace();
}
databaseManagementService.shutdown();
}
} 可以注意到的是,只有 queryByDriver() 和 queryByJdbc() 需要提供帳號及密碼,並且需要連接一個已經啟動的 neo4j Database server。而 queryByEmbeddedMode() 不需帳號、密碼,也不需要一個已經啟動的 neo4j Database server,
它會直接對本地端的 neo4j Database folder 做存取,因為它會自己啟動 DB server ,
所以不要用例如上述的 neo4j console 指令啟動 server,不然可能會出現
Exception in thread "main" java.lang.RuntimeException: Error starting Neo4j database server at D:\xxx\yyy\neo4j-community-4.4.2\data\databases
的錯誤訊息。
原碼下載分享:
沒有留言 :
張貼留言