天天看點

neo4j 初探

neo4j 初探

參考 轉載:http://shomy.top/2018/06/08/neo4j-start/

近期需要處理圖資料,考察後打算使用neo4j, 相比其他一些圖資料庫,neo4j開源,跨平台,接口友好,文檔齊全,完整支援ACID。 首先放一張網上的圖檔,關系型資料庫與圖資料庫存儲網絡資料的差異:

neo4j 初探

初次接觸neo4j 踩了不少坑,這裡記錄一下。

關于如何安裝Neo4j和使用web ui進行查詢操作就不再贅述。

Cypher基本操作

相比關系型資料庫的SQL查詢語言,Neo4j的查詢語言為

Cypher

,文法更加友好,更适合圖資料做查詢操作。

概念

首先介紹在圖資料裡面幾個概念:

  • 節點(Node): 使用小括号表示

    (n)

    表示n這個節點,同時一般都會賦予節點某個标簽(Label), 等同于關系書庫裡面的表名。比如

    (n: Person)

    表示n是一個

    Person

    類的節點,當然一個節點可以同時有多個label.
  • 關系(Relation):關系使用中括号表示

    [r:Knows]

    表示

    r

    Knows

    這種關系。兩個節點的關系用

    --

    表示,如果有方向的話,加個箭頭即可。如

    (a)-[r:Knowns]->(b)

    表示節點a和b之間有r關系,其中

    Knowns

    r

    的類型
  • 屬性(Property): 節點和關系都可以附帶屬性,這個也是圖資料庫的優勢,儲存屬性非常友善,直接用key-value表示即可。比如

    (n:Person{name:"John"})

    表示一個含有屬性name值為John節點n。同樣關系也可以有屬性:

    **[r:Knows]{year: 2018}**

    表示為r賦予一個year屬性。

關鍵字

幾個常用的關鍵字介紹:

  • MATCH: 表示查詢,是讀資料庫操作。比如查屬于Person的節點:

    MATCH (n:Person)

    ,查找姓名為“John”的節點:

    MATCH (n:Person){name: "John"}

    或者使用

    where

    語句:

    MATCH (n:Person) WHERE n.name="John"

    。當然這裡面很多文法可以使用,比如正則比對等,這裡就不再贅述了。當然在實際使用中,MATCH不能單獨使用,需要結合

    RETURN

  • CREATE: 表示建立,可以新增節點,關系,索引,限制等等,是一種寫操作。比如

    CREATE (n:Person{name:"Ana"})

    表示建立一個name為“Ana”的Person類的節點。在建立的同時可以設定屬性:

    CREATE (n:Person{name:"Ana"}) set n.age=20

    。同樣在某個屬性上建立索引:

    CREATE INDEX ON :Person(name)

    ,這裡需要提一下,盡量所有的Label都設定索引或者UNIQUE限制,在後續的讀操作比如MATCH會大大提高性能(建立索引可以在導入節點之前執行)。
  • DELETE: 表示删除節點,關系等,也是寫操作。一般需要結合

    MATCH

    比對查詢要删除的節點。

    MATCH (n:Person) DELETE n

    。如果在删除有關系的節點,這樣删除會報錯,可以先删除邊

    MATCH (n:Person)-[r:KNOWS]->() DELETE r

    再删除節點。不過更推薦使用

    DETACH DELETE

    來級聯删除,

    MATCH (n:Person) DETACH DELETE n

    可以同時删除節點及節點的關系。
  • MERGE:合并節點或者關系,屬于先讀後寫操作,相當于

    MATCH + CREATE

    ,先檢查資料庫中節點/關系是否存在,如果存在的話就不再建立,反之執行CREATE。如:
    MERGE(a:Person{name:“John”}) on create set a.age=20 //建立節點,先檢測是否存在           
    // 給節點a,b建立關系,如果a,b已經存在,就無需建立。
    MATCH (a:Person{name:“John”}),            
    (b:Person{name:“Ana”}) MERGE (a)-[:KNOWS]->(b)           

這幾個隻是最基本的操作,在複雜查詢中,會用到諸如

WITH, UNWIND

等指令。這裡不再較長的描述。

注意事項

  • 節點名稱與節點Label的定義容易混亂。比如

    CREATE (n:Person)

    建立了一個屬于Person的節點n。這裡的n僅僅屬于一個變量名,跟節點本身沒有關系,指令執行結束,n的生命周期也就結束了,而Person則是節點本身的Label,會一直存在。
  • 索引一定要建立(建立在某類的節點上當中),例如:CREATE INDEX ON :Person(id)

快捷鍵

關于Neo4j浏覽器的初次使用有幾個快捷鍵:

  • 預設單行輸入,按回車執行指令
  • 輸入一行指令之後,按

    SHIFT + ENTER

    進入多行輸入狀态(也就是之後不用在多次按住shift+enter)
  • 在多行輸入時,

    CTRL + ENTER

    執行指令
  • **ESC

    可以放大輸入框至螢幕大小,複雜查詢的時候,很友善**。

記憶體配置

關于記憶體配置的幾個參數記憶體配置:

  • dbms.memory.heap.initial_size

  • dbms.memory.heap.max_size

  • dbms.memory.pagecache.size

    pagecache(頁面緩存)
  • 可以使用

    neo4j-admin memrec

    來根據目前資料庫資料,檢視推薦的記憶體配置(memory recommend) 分别取前三位
bin/neo4j-admin memrec --database=graph.db           

file:///

就是用file:///加上對應檔案的位址,打開對應的本地電腦(或者你所連接配接到的電腦的 ->估計指的是像windows中映射出來其他網絡鄰居中某個計算機為某個網盤的情況)中對應的檔案。

用file:///+檔案的位址,其實就等價于檔案的位址,

即:

file:///C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter1627300719/supfiles52F410/wangdan-se-436963[2].jpg

其實就等價于;

C:/Users/CLi/AppData/Local/Temp/WindowsLiveWriter1627300719/supfiles52F410/wangdan-se-436963[2].jpg

使得(此處Html源碼中所允許的位址,對應的WLW程式)可以通路對應的檔案而已。

neo4j load csv導入問題

導入node時一般用create語句,導入關系時一般用merge語句,防止重複導入

WITH HEADERS表明csv檔案的第一行是屬性名。

neo4j的節點與标簽關系:

MERGE (<node-name>:<label-name>
{
   <Property1-name>:<Pro<rty1-Value>
   .....
   <Propertyn-name>:<Propertyn-Value>
})           

節點模式的構成:(Variable:Lable1:Lable2{Key1:Value1,Key2,Value2}),實際上,每個節點都有一個整數ID,在建立新的節點時,Neo4j自動為節點設定ID值,在整個資料庫中,節點的ID值是遞增的和唯一的。

導入資料

這一部分主要記錄下如何将圖資料從檔案中導入庫,常見的格式為CSV和JSON格式。

導入CSV 格式資料

Neo4j内置了指令來導入CSV資料:使用方法也很簡單。假設CSV格式如下:

"Id","Name","Year"
"1","ABBA","1992"
"2","Roxette","1986"
"3","Europe","1979"
"4","The Cardigans","1992"           

直接使用如下指令導入并直接引用headers來表示屬性并建立節點:

#WITH HEADERS 表示的是使用csv檔案當中第一行的屬性名,為之後的key:value映射做準備.(很重要)
LOAD CSV WITH HEADERS FROM 'FILE:/artists.csv' AS line
#可以沒有節點名,直接:标簽名
CREATE (:Artist { name: line.Name, year: toInteger(line.Year)})           

注意事項:

  • 分隔符預設是

    ,

    , 可以用

    FIELDTERMINATOR

    自定義分隔符:LOAD CSV WITH HEADERS FROM ‘FILE:/artists.csv’ AS line FIELDTERMINATOR “;”
  • 檔案位置: 可以直接使用URL位址作為檔案位置,如果是本地檔案的話,直接使用“FILE:”表明,檔案的位置是相對位置,在配置檔案

    neo4j.conf

    中的

    dbms.directories.import

    參數可以指定,預設是neo4j安裝目錄下的

    import

    檔案夾,将CSV檔案放到該目錄下即可。
  • 對于大規模資料,如果一次性導入可能會超記憶體,此時可以用

    PERIODIC COMMIT

    來分批送出導入資料,預設是1000行送出一次,具體如下:
#PERIODIC:代表的是周期性的,commit:送出
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM...
....           
  • 文本内容存在

    "

    的字段需要特殊處理

一般使用:

field terminated by ','           
optionally enclosed by '"'           
lines terminated by '\r'           

導入JSON格式資料

圖資料裡面更常見的則是JSON資料, 假設資料格式如下:

[
    {
    "id":1, "friends":[2,3], "name": "Bob", "age": 27,
    "book":[{"name":"book1", "year":2000}, {"name":"book3", "year":1990}]
    },
    {
    "id":2, "friends":[1], "name": "Alice", "age": 29,
    "book":[{"name":"book1", "year":2000}, {"name":"book2", "year":1999}]
    },
    {
    "id":3, "friends":[2], "name": "John", "age": 20,
    "book":[{"name":"book3", "year":1990}]
    }
]           

​ 清單中每一個map都代表一個User, 其屬性有

id

,

name

age

; 同時

friends

字段表示朋友關系,

book

字段表示讀過某本書。 現在我們需要建立 Person 和 Book兩類節點,同時Person和Book 之間有READ關系。

APOC

實際上就是一個使用者過程存儲庫300+函數)

a package of component :元件包

變為

awesome procedure on cypher:超級棒的存儲過程

Neo4j 并沒有内置直接導入Json的函數,不過在Neo3.3版本之後,推出了一個函數存儲包APOC,裡面包含了非常豐富的函數和存儲過程,如各種圖計算算法,是Cypher的有力補充,其中就包含了從Json中導入資料。安裝APOC很簡單,隻需要三步:

  • 從github中下載下傳與Neo4j對應版本的APOCjar包
  • 将jar包拷貝到neo4j安裝目錄的plugins目錄下
  • 在配置檔案neo4j.conf中加入一行允許APOC導入檔案:apoc.import.file.enabled=true
  • 重新開機Neo4j即可

在Neo4j浏覽器中,輸入

return apoc.version()

即可檢視版本号

neo4j 初探

此外我們可以看到apoc支援導入非常多格式的資料:

neo4j 初探

導入方式很簡單,我們要建立兩類節點,首先建立索引,友善後續導入。

CREATE INDEX ON :Person(id)
#不能一起建立索引,需要分開分步執行.
CREATE INDEX ON :Book(name)           

否則會報錯:

Neo.ClientError.Statement.SyntaxError: Invalid input 'C': expected whitespace, comment, ';' or end of input (line 2, column 1 (offset: 28))
"CREATE INDEX ON :Book(name)"           
neo4j 初探

導入代碼如下:

// YIELD關鍵字表示每次導入json資料中的一組資料,即`[...]`中的每一個`{}`, 這裡的person.json是系統絕對路徑
CALL apoc.load.json("file:///D:/neo4j-community-3.4.0/import/person.json") YIELD value as person    //這個最好是絕對路徑,否則會報錯.(重點注意)
// 需要對book屬性進行清單展開,後續建立Person和Book關系的時候,需要用。
UNWIND person.book as book
// 建立Person節點
MERGE (p:Person{id:person.id})
SET p.name=person.name, p.age=person.age, p.friends=person.friends
//建立book節點
MERGE (b:Book{name:book.name})
SET b.year=book.year
//建立person->book關系
MERGE (p)-[:READ]->(b)           

然後再根據已有的

friends

導入

Friend

關系:

//對每一個 person周遊
MATCH (p:Person)
// 對p的friends進行清單展開,
UNWIND p.friends as f
// 根據id搜尋Person節點
MATCH (q:Person{id:f})
// 建立關系
MERGE (p)-[:Friend]-(q)           

執行完成之後,可視化看一下 ,:

neo4j 初探

neo4j浏覽器界面說明

  • 左側(看上圖就可以)是資料庫的基本資訊:包括節點标簽,連接配接類型,*代表全部情況(各個類型的全部情況),屬性,目前連接配接者,neoj資料庫版本資訊:
  • 第一行:(*)6:代表節點的總個數;person(3):代表person類節點的個數是3,
  • 第二行:(*)8代表連接配接數的總個數,Friend(3)是friend連接配接類型的邊數有三個,後面以此類推
neo4j 初探
  • 上圖左側五角星那項是專門用來 儲存一些基本和自定義的腳本代碼–cypher語句(在右側左上角點選收藏之後重新整理就會看到),便于加快速度,可以分類,添加的話可以拖拽相關類型檔案添加.
  • 類似書本那項則是關于neo4j的說明文檔,cypher語句的技術手冊.
  • 紅雲朵那項則是用來雲同步的(可選項,)可以清除目前登入資訊.clear all data
  • 左側齒輪狀選項則是用來設定neo4j的浏覽器界面的(有主題,和顯示結果的個數設定)
  • 左側最下角的是關于neo4j的版本資訊

​ 到這裡導入基本完成了,不過還有一點問題,暫時沒有解決,使用

UNWIND person.book as book

的時候,如果某個節點沒有book這個一個屬性,那麼後續代碼将不再執行,即該Person節點不會建立。但是如果将UNWIND放到建立Person之後,建立的READ關系會有問題,還在查找原因。

參考資源

  • 官方文檔
  • Neo4j應用