neo4j使用文檔


概述

1、Neo4j是一個高性能的,NOSQL圖形數據庫,它將結構化數據存儲在網絡上而不是表中。它是一個嵌入式的、基於磁盤的、具備完全的事務特性的Java持久化引擎,但是它將結構化數據存儲在網絡(從數學角度叫做圖)上而不是表中。

2、Neo4j也可以被看作是一個高性能的圖引擎,該引擎具有成熟數據庫的所有特性。程序員工作在一個面向對象的、靈活的網絡結構下而不是嚴格、靜態的表中——但是他們可以享受到具備完全的事務特性、企業級的數據庫的所有好處。(摘自百度百科)

3、Neo4j圖數據庫遵循屬性圖模型來存儲和管理其數據。

屬性圖模型規則

  • 表示節點,關系和屬性中的數據
  • 節點和關系都包含屬性
  • 關系連接節點
  • 屬性是鍵值對
  • 節點用圓圈表示,關系用方向鍵表示。
  • 關系具有方向:單向和雙向。
  • 每個關系包含“開始節點”或“從節點”和“到節點”或“結束節點”
  • 在屬性圖數據模型中,關系應該是定向的。如果我們嘗試創建沒有方向的關系,那么它將拋出一個錯誤消息。

4、在Neo4j中,關系也應該是有方向性的。如果我們嘗試創建沒有方向的關系,那么Neo4j會拋出一個錯誤消息,“關系應該是方向性的”。

5、Neo4j圖數據庫將其所有數據存儲在節點和關系中。我們不需要任何額外的RRBMS數據庫或無SQL數據庫來存儲Neo4j數據庫數據。它以圖形的形式存儲其數據的本機格式。

6、圖形數據庫數據模型的主要構建塊是:節點、關系、屬性

7、neo4j主要存儲節點和關系,其中關系必須為有向關系,描述節點和關系的數據以屬性的形式存儲,節點和關系上都能放鍵值對的屬性。不同類型的節點和關系通過標簽Label來區別,不同標簽的節點代表不同類型節點,不同標簽關系代表不同類型關系,示例:

創建一個標簽為Person的節點,其有屬性 name 和age:create (:Person{name:'小紅',age:21});

查詢一個節點:match (m:Person{name:'小紅',age:21}) return n;

刪除一個節點:match (m:Person{name:'小紅',age:21}) delete n;

 

創建關系:create (a:Person{name:"a"}),(b:Person{name:"b"}) with a,b create (a)-[r:Friend]->(b);

查詢關系:match (a:Person{name:"a"})-[r:Friend]->(b:Person{name:"b"}) return r;

刪除關系:match p=(a:Person{name:"a"})-[r:Friend]->(b:Person{name:"b"}) delete p;

 

其中create還有個近似的操作merge,也可以創建數據,其中merge可以看做match和create的合體。merge會先去原始庫match屬性或標簽,如果不存在會創建,可以結合on create 和on match使用,如:

  • 在創建的時候使用on create(在創建時進行一些操作)---如果存在name為Keanu Reeves的Person節點,則新增或修改屬性created 屬性,否則新增節點

MERGE (keanu:Person { name: 'Keanu Reeves' }) ON CREATE SET keanu.created = timestamp() RETURN keanu.name, keanu.created

  • 在創建的時候使用 on match---如果有Person標簽的節點,則更新found 屬性,否則不做操作

MERGE (person:Person) ON MATCH SET person.found = TRUE RETURN person.name, person.found

  • 同時使用on create 和 on match---如果存在name為Keanu Reeves的Person節點,則執行on match操作,否則執行on create操作

MERGE (keanu:Person { name: 'Keanu Reeves' }) ON CREATE SET keanu.created = timestamp() ON MATCH SET keanu.lastSeen = timestamp() RETURN keanu.name, keanu.created, keanu.lastSeen

插入數據

目前主要有以下幾種數據插入方式:

  • Cypher create 語句,為每一條數據寫一個create
  • Cypher load csv 語句,將數據轉成CSV格式,通過LOAD CSV讀取數據。
  • 官方提供的neo4j-import工具,未來將被neo4j-admin import代替
  • 官方提供的Java API - BatchInserter
  • 大牛編寫的 batch-import 工具
  • neo4j-apoc  load.csv + apoc.load.relationship
just try create語句 load csv語句 neo4j-import BatchInserter batch-import apoc
適用場景 1 ~ 1w 0 ~ 1000w 千萬以上 千萬以上 千萬以上 1 ~ 數千萬
速度 很慢 1000/s 一般 5000/s 非常快 x w/s 很快 x w/s 很快x w/s 1w /s
實際測試 9.5k/s(節點+關系)
用到了merge,數據量越大,速度越慢
12w/s(節點+關系) 1w/s(節點+關系) 1w/s(節點+關系) 4k/s(1億數據上增量更新)
1w/s(百萬數據上更新)
用到了merge,數據量越大,速度越慢
優點 1.使用方便
2.可實時插入
1.官方ETL工具
2.可以加載本地/遠程CSV
3.可實時插入
1.官方工具
2.占用資源少
1.官方API 1.可以增量更新
2.基於BatchInserter
1.官方ETL工具
2.可以增量更新
3.支持在線導入
4.支持動態傳Label RelationShip
缺點 1.速度慢
2.處理數據,拼CQL復雜,很少使用
1.導入速度較慢
2.只能導入節點
3.不能動態傳Label RelationShip
1.需要脫機導入 停止Neo4j數據庫
2.只能用於初始化導入
1.只能在JAVA中使用
2.需要脫機導入 停止Neo4j數據庫
1.需要脫機導入 停止Neo4j數據庫 1.速度一般

比對:

 

  • neo4j-import導入速度快,但是要求是空庫,導入時要停止neo4j,也就是脫機導入,而且你要提前處理好數據,數據最好不要有重復,如果有重復,可以導入時跳過,然后根據bad.log來查看或者修正這部分數據
  • batch-import可以增量導入,但是要求導入時停止neo4j數據庫(脫機導入),而且增量更新的數據不會和庫里存在的數據對比,所以要求數據全是新的,否則會出現重復數據
  • load csv比較通用,而且可以在neo4j數據庫運行時導入,但是導入速度相對較慢,要提前整理好數據,而且不能動態創建 Label RelationShip
  • apoc挺好用的,可以動態創建RelationShip,但是不能動態創建Label (動態創建Label只能在程序里通過拼接字符串的方法實現)

 

實際情況中,處理數據比導入數據更花費時間

(這里介紹我使用過的create、neo4j-import、load csv方法)

1、neo4j-import批量導入,如上所述,導入很快,需要停止neo4j服務才能進行導入,否則會導入失敗(適合用於初始化,否則會影響正在使用的服務);需要導入的庫不存在,如果存在需要刪除對應的.db文件再執行,否則導入會失敗;需要事先把要導入的數據按特定格式整理好放入csv中(這里可以參照ba-es項目的service.KnCallsBulkPut類),這里以導入通話記錄關系為例

節點csv(person.csv)格式:(其中節點標簽為Person,屬性有personId、name,且personId的值為節點ID)

personId:ID(Person),name

13661909859,鄭敏

angeloo68@163.com,李曉芊

15107253239,胡強

關系csv(rels.csv)格式:(其中:START_ID為關系起始點的id,對應上面節點的ID,:END_ID為關系結束點的id,對應上面節點的ID,in,out分別別關系的屬性)

:START_ID(Person),in,out,:END_ID(Person)

13545342144,0,300,15207123026

18016315333,0,50000,1529703684@qq.com

13661909859,0,2000.0,855-0979212256

13661909859,0,22210.0,15880082973

執行初始化批量錄入命令:

.../neo4j-community-3.3.5/bin/neo4j-import —multiline-fields=true —bad-tolerance=0 —into .../neo4j-community-3.3.5/data/databases/caifen.db —nodes:Pesron .../person.csv —relationships:CALLWITH .../rels.csv (其中bad-tolerance指定你能容忍的錯誤數據量,如果對數據精度要求不高可以放大,這樣在導入過程中,即使有小於設置值數量的數據錯誤,導入不報錯,正確的數據能導入成功。.../neo4j-community-3.3.5/data/databases目錄下如果已經有caifen.db,執行命令會報錯,需要手動刪除。--nodes:、--relationships:可以拼接多個,后面跟的分別是節點標簽和關系標簽,再后面跟着的是對應生成對應節點和關系的csv文件

2、load csv使用(當前公司用於導入蟲洞數據更新到已有庫里)

使用方式:

neo4j自帶客戶端瀏覽器訪問:http://ip:7474,如 http://192.168.0.246:7474

進到neo4j的安裝目錄的bin目錄下(需要先進到neo4j-community-3.3.5/conf/neo4j.conf放開dbms.shell.port的注釋,再重啟),執行neo4j-shell

把整理好的文檔放入對應目錄,然后通過上面兩種方式進入命令行執行:

[USING PERIODIC COMMIT 500] LOAD CSV [ WITH HEADERS] FROM “file:///rels20190717.csv”[W] AS line with line merge (n:Suspect{personId:line[0]}) on match set n.name=case when line[1] <> line[0] then line[1] else n.name end on create set n.personId=line[0],n.name=line[1] with line,n merge(m:Suspect{personId:line[2]}) on match set m.name=case when line[2] <> line[3] then line[3] else m.name end on create set m.personId=line[2],m.name=line[3] with n,m,line merge (n)-[r:CAPITALFLOWING]->(m)

說明:上面命令中[]里的命令為可選,[USING PERIODIC COMMIT 500] 表示 每500 行進行一次事務提交, [ WITH HEADERS] 導入時是否帶csv中的表頭,其中帶表頭用的是 line.name ,反之用的是 line[0]。導入命令中還可以用 toInt(‘1’) toFloat(‘1.0’)toInteger(), toFloat(), split()對數據進行處理;其中fill:后面跟的是文檔路徑,可以使絕對路徑也可以是相對路徑,neo4j默認是從neo4j-community-3.3.5/import中讀取文件的,上面示例的寫法就是將csv放在import文件夾下的寫法;windows下相對路徑方式如:file:/Test.csv,windows下絕對路徑方式如:file:///C:/User/wdb/2017-04-06_test.csv,linux下相對路徑格式:file:/2017-04-06_test.csv,linux下絕對路徑格式:file:/home/wkq/databases/data/2017-04-06_test.csv;

3、插入一條數據,前面已經介紹過了,上面兩種方式進入到命令行,執行create或merge進行數據插入,這里介紹unwind list+create(一條一條數據錄入)在java API中的使用(掃黑數據的錄入程序中)

if (phSet.size() > 0) {
								for (String eachph : phSet) {
									if (!MiscUtils.isNullOrEmpty(sfz)) {
										String temp = "{sfz:\"" + sfz + "\",name:\"" + name + "\",sex:\"" + sex
												+ "\",ph:\"" + eachph + "\",rksj:\"" + rksj + "\"}";
										sfzPhoneSet.add(temp);
									}
								}
							}

...

		StringBuilder sb = new StringBuilder();
				// 存在擁有手機關系
				if (sfzPhoneSet.size() > 0) {
					sb.append("UNWIND " + sfzPhoneSet + " as row with row ");
					sb.append(
							" merge (n1:Mobile{phone:row.ph})  on create set n1.phone=row.ph,n1.iskey=toString(0),n1.personId=row.ph,n1.rksj=row.rksj with n1,row ");
					sb.append(
							" merge (n2:Person{sfz:row.sfz}) on match  set n2.name=case when row.name<> '' then row.name else n2.name end,n2.sex=case when row.sex<> '' then row.sex else n2.sex end,n2.rksj=case when row.rksj<> '' then row.rksj else n2.rksj end  ");
					sb.append(" on create set n2.sfz=row.sfz,n2.name=row.name,n2.sex=row.sex,n2.rksj=row.rksj ");
					sb.append(" with n1,n2,row merge (n2)-[r:OWNPHONE]->(n1) ");
					neo4jJDBCHelper.executeQuery(sb.toString().replace("\\\\'", "\\'"), new QueryCallBack() {

						@Override
						public void process(ResultSet rs) throws Exception {

						}

					});
					sb = null;
				}
 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM