目錄
數據分析(data profiling)能夠用於分析數據源的結構、內容和元數據,是關係型數據庫廣泛應用的方法。通常情況下,數據剖析包含對數據源的一系列操作,以獲取底層數據的統計信息、信息摘要。一般來說,數據是隨着時間而發展的。幾年之後,數據庫中存儲和使用的實際數據可能與人們認爲的有很大的不同,或者與數據庫最初設計的目的有很大的不同。數據分析不僅有助於理解異常和評估數據質量,而且有助於發現、註冊和評估企業元數據。Neo4j圖形數據庫是分析連接的、高容量的和可變結構的數據資產的最佳工具,這使得數據分析更加關鍵,因爲它將幫助我們更好地理解數據,更容易地識別隱藏的模式,並可能提高查詢性能。
本文將使用Cypher圖形查詢語言共享實用的數據分析技術。
1. 數據準備
(1)數據下載
數據採用截止2015年8月22日的Stack Overflow論壇中neo4j板塊討論數據,其下載地址 http://example-data.neo4j.org/files/stackoverflow/stackoverflow-2015-08-22.db224.tgz?_ga=2.207962901.662760037.1557307514-1383806388.1557307514
(2)數據格式
Nodes:
posts.csv數據格式 postId:ID(Post),title,postType:INT,createdAt,score:INT,views:INT,answers:INT,comments:INT,favorites:INT,updatedAt,body
users.csv數據格式 userId:ID(User),name,reputation:INT,createdAt,accessedAt,url,location,views:INT,upvotes:INT,downvotes:INT,age:INT,accountId:INT
tags.csv數據格式 tagId:ID(Tag),count:INT,wikiPostId:INT
Relationships:
posts_answers.csv:ANSWER -> :START_ID(Post),:END_ID(Post)
posts_rel.csv:PARENT_OF -> :START_ID(Post),:END_ID(Post)
tags_posts_rel.csv:HAS_TAG > :START_ID(Post),:END_ID(Tag)
users_posts_rel.csv:POSTED > :START_ID(User),:END_ID(Post)
2. 數據導入
2.1 常見數據導入方式概覽
(1) Cypher create語句,爲每一條數據寫一個create;
(2) Cypher load csv語句,將數據轉成CSV格式,通過LOAD CSV讀取數據;
(3) 官方提供的neo4j-import工具,未來將被neo4j-adminimport代替;
(4) 官方提供的Java API BatchInserter;
(5) 大牛編寫的 batch-import 工具;
(6) neo4j-apocload.csv +apoc.load.relationship;
(7) 針對實際業務場景,定製化開發。
2.2 導入工具對比
create語句 |
load csv語句 |
neo4j-import |
BatchInster |
batch-import |
apoc |
|
適用場景
|
初始化導入 增量更新
|
初始化導入
|
初始化導入
|
初始化導入 增量更新(有限制)
|
增量更新 |
|
導入速度 |
很慢1000/s |
數k /s |
數w/s |
數w/s |
數w/s |
數k/s |
實際測試 |
無 |
9.5k/s (節點+關係) |
12w/s (節點+關係) |
1w/s (節點+關係) |
1w/s (節點+關係) |
4k/s(1億數據上增量更新) 1w/s(百萬數據上增量更新) |
優點 |
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.不能動態傳Label RelationShip |
1.需要脫機導入 停止Neo4j數據庫 2.只能用於初始化導入 |
1.需要脫機導入 停止Neo4j數據庫 2.需要在JAVA環境中使用
|
1.需要脫機導入 停止Neo4j數據庫 |
1.速度一般 |
2.3 該實例中數據導入
該實例中文件大小共9.46GB,31138559 nodes、77930024 relationships、260665346 properties,數據量大,採用初始導入 neo4j-import工具,此時須關閉neo4j進程,並刪除neo4j數據庫中其他數據。
Import工具命令格式如下:
neo4j-admin import [--mode=csv] [--database=<name>]
[--additional-config=<config-file-path>]
[--report-file=<filename>]
[--nodes[:Label1:Label2]=<"file1,file2,...">]
[--relationships[:RELATIONSHIP_TYPE]=<"file1,file2,...">]
[--id-type=<STRING|INTEGER|ACTUAL>]
[--input-encoding=<character-set>]
[--ignore-extra-columns[=<true|false>]]
[--ignore-duplicate-nodes[=<true|false>]]
[--ignore-missing-nodes[=<true|false>]]
[--multiline-fields[=<true|false>]]
[--delimiter=<delimiter-character>]
[--array-delimiter=<array-delimiter-character>]
[--quote=<quotation-character>]
[--max-memory=<max-memory-that-importer-can-use>]
[--f=<File containing all arguments to this import>]
[--high-io=<true/false>]
對於該實例,進入bin文件夾,打開終端,命令如下:
提示:由於neo4j-import只能初始導入,須刪除/data/databases/中graph.db數據庫文件
./neo4j-import \
--into ../data/databases/graph.db \
--id-type string \
--nodes:Post ../../stackoverflow-2015-08-22/posts.csv \
--nodes:User ../../stackoverflow-2015-08-22/users.csv \
--nodes:Tag ../../stackoverflow-2015-08-22/tags.csv \
--relationships:PARENT_OF ../../stackoverflow-2015-08-22/posts_rel.csv \
--relationships:ANSWER ../../stackoverflow-2015-08-22/posts_answers.csv \
--relationships:HAS_TAG ../../stackoverflow-2015-08-22/tags_posts_rel.csv \
--relationships:POSTED ../../stackoverflow-2015-08-22/users_posts_rel.csv
2.4 neo4j進程開啓
(1)由於數據量巨大,須更改neo4j配置信息
打開conf/neo4j.conf,配置dbms.memory.heap.max_size=10240m
(2)然後輸入 ./neo4j.bat start 開啓數據庫
在網頁端打開http://localhost:7474/browser/,並檢驗數據是否導入成功。
輸入:
match (n) return head(labels(n)) as label, count(*);
輸出:
輸入:
match ()-[r]-() with type(r) as RelationshipName,
count(r) as RelationshipNumber
return RelationshipName, RelationshipNumber;
輸出:
(3)爲節點屬性添加索引和約束
輸入:
create index on :Post(title);
create index on :Post(createdAt);
create index on :Post(score);
create index on :Post(views);
create index on :Post(favorites);
create index on :Post(answers);
create index on :Post(score);
create index on :User(name);
create index on :User(createdAt);
create index on :User(reputation);
create index on :User(age);
create index on :Tag(count);
create constraint on (t:Tag) assert t.tagId is unique;
create constraint on (u:User) assert u.userId is unique;
create constraint on (p:Post) assert p.postId is unique;
3. 數據庫模式分析
數據庫模式分析通常是數據分析的第一步。它的簡單目的是瞭解數據模型是什麼樣子的,以及有哪些對象可用。
3.1 圖數據模型展示
輸入:
CALL db.schema()
該數據庫包含User、Post和Tag三類節點,並且具有User POSTED Post、Post HAS_TAG Tag、Post is PARENT_OF Post和Post ANSWER another Post四類關係。
3.2 現有約束和索引展示
輸入:
:schema
輸出:
索引告訴我們用於匹配時具有最佳查詢性能的屬性,約束告訴我們哪些屬性是惟一的,可以用來標識節點或關係。
3.3 所有關係類型展示
輸入:
CALL db.relationshipTypes()
輸出:
3.4 所有節點標籤(類型)展示
輸入:
CALL db.labels()
輸出:
3.5 節點個數統計
輸入:
MATCH (n) RETURN count(n)
輸出:
3.6 關係個數統計
輸入:
MATCH ()-[r]->() RETURN count(*)
輸出:
3.7 數據存儲空間展示
輸入:
:sysinfo
輸出:
3.8 數據採樣
採樣一些節點,統計節點的屬性、關係
輸入:
MATCH (n) WHERE rand() <= 0.1
RETURN
DISTINCT labels(n),
count(*) AS SampleSize,
avg(size(keys(n))) as Avg_PropertyCount,
min(size(keys(n))) as Min_PropertyCount,
max(size(keys(n))) as Max_PropertyCount,
avg(size( (n)-[]-() ) ) as Avg_RelationshipCount,
min(size( (n)-[]-() ) ) as Min_RelationshipCount,
max(size( (n)-[]-() ) ) as Max_RelationshipCount
輸出:
結果分析:隨機選取10%節點,統計其節點個數、平均屬性個數、最小屬性個數、最大屬性個數、平均關係個數、最小關係個數、最大關係個數
4. 節點分析
節點分析或多或少類似於關係數據庫(RDBMS)概要分析的表和列分析。節點分析的目的是揭示節點的事實以及節點的屬性。
4.1 根據節點的標籤/類型統計
輸入:
MATCH (n) RETURN labels(n) AS NodeType, count(n) AS NumberOfNodes;
輸出:
結果分析:統計每一類節點的個數
4.2 屬性分析
(1)列出一類節點的屬性
輸入:
MATCH (u:User) RETURN keys(u) LIMIT 1
輸出:
結果分析:統計屬性名稱
(2)列出一類關係的屬性
輸入:
MATCH ()-[t:POSTED]-() RETURN keys(t) LIMIT 1
輸出:
無
結果分析:該數據關係沒有屬性
(3)列出屬性的唯一性
輸入:
MATCH (u:User)
RETURN count(DISTINCT u.name) AS DistinctName,
count(u.name) AS TotalUser,
100*count(DISTINCT u.name)/count(u.name) AS Uniqueness
輸出:
結果分析:統計用戶名稱的唯一性
(4)屬性的非空性
輸入:
MATCH (u:User) WHERE u.name IS null RETURN count(u);
輸出爲空
結果分析:說明所有用戶都有名字
(5)屬性值的最小值、最大值、平均值和標準差
輸入:
MATCH (p:Post)
RETURN min(p.favorites) AS MinFavorites,
max(p.favorites) AS MaxFavorites,
avg(p.favorites) AS AvgFavorites,
stDev(p.favorites) AS StdFavorites;
輸出:
(6)屬性值的出現次數
輸入:
MATCH (p:Post)
RETURN p.answers AS Answers, count(p.answers) AS CountOfAnswers
ORDER BY Answers ASC;
輸出:
結果分析:117萬問題有0個回答,1413個問題有15個回答
4.3 節點等級
(1)用戶重要性
統計用戶的出度、入度
輸入:
MATCH (u:User)
WITH u,size( (u)-[:POSTED]->()) AS OutDepth, size( (u)<-[:POSTED]-()) AS InDepth
ORDER BY OutDepth, InDepth
WHERE u.name STARTS WITH 'T'
RETURN u.name, min(OutDepth), max(OutDepth), min(InDepth), max(InDepth)
輸出:
輸入:
MATCH (u:User) return u,size( (u)-[:POSTED]->()) AS OutDepth, size( (u)<-[:POSTED]-()) AS InDepth order by OutDepth desc limit 10
輸出:
(2)問題重要性
統計問題被回答的數量
輸入:
match (p:Post) return p.name, size(()-[:ANSWER]->(p)) as InDepth, size((p)-[:ANSWER]->(p)) as OutDepth order by InDepth desc limit 10
輸出:
4.4 孤立節點
輸入:
match (u:User)
with u,size( (u)-[:POSTED]->()) as posts where posts = 0
return u.name, posts;
輸出:
5. 關係分析
關係分析有助於理解節點間的完整性、密度。與普通RDBMS相比,圖形數據庫的獨特之處在於可用於揭示隱藏的連接數據知識的強大分析。 一個例子是找出兩個節點之間的最短路徑。 另一個是識別關係三角形。
5.1 關係統計分析
輸入:
match (u)-[p]-() with type(p) as RelationshipName,
count(p) as RelationshipNumber
return RelationshipName, RelationshipNumber;
輸出:
5.2 兩個節點間最短路徑
輸入:
MATCH path =
allShortestPaths((u:User {name:"Darin Dimitrov"})-[*]-(me:User {name:"Michael Hunger"}))
RETURN path;
輸出:
結果分析:兩個用戶之間的最短路徑 - 在上圖中用藍色箭頭突出顯示 - 告訴我們兩個用戶通過具有相同標籤的帖子(黃色節點)連接。 這些不一定是唯一的路徑,因爲用戶可以發帖回答彼此的問題或帖子,但在這種情況下,通過相同標籤的連接 - 即,感興趣的公共區域 - 是連接兩個用戶的最快方式。
在像這樣的大圖中,計算任何兩個用戶之間的最短路徑可能是不可行的。 但是,檢查最重要的人之間或最感興趣的帖子之間的連接可能是有價值的。
5.3 三角性分析
輸入:
match (u:User)-[p1:POSTED]-(x1),(u)-[p2:POSTED]-(x2),(x1)-[r1]-(x2)
where x1 <> x2 return u,p1,p2,x1,x2 limit 10;
輸出:
輸入:
match (u:User)-[p1:POSTED]-(x1),(u)-[p2:POSTED]-(x2),(x1)-[r1]-(x2)
where x1 <> x2 return count(p1);
輸出:三角形個數
結果分析:其中x1 <> x2爲x1!=x2,三角形是圖論中的另一個關鍵概念。 三角形由三個連接的節點表示,方向或單向。 識別三角形 - 或缺少三角形 - 提供有關基礎數據資產的有趣見解。三角形也被稱爲三元閉包,根據圖形數據庫,第2版(O'Reilly Media),三元閉包是社交圖的共同屬性,我們觀察到如果兩個節點通過涉及第三節點的路徑連接,則兩個節點在將來的某個點上將直接連接的可能性增加。
把這個概念融入我們的日常生活中,這是一個熟悉的社會事件。 如果我們碰巧是兩個不認識的人的朋友,那麼這兩個人將來會在某個時刻成爲直接朋友的可能性會增加。
通過在圖形數據庫中發現三角形的存在,我們可以創建更有效的查詢以避免循環遍歷。
6. 使用APOC庫
從Neo4j 3.0開始,用戶可以使用Java實現定製功能,從而將Cypher擴展爲高度複雜的圖形算法。 這就是所謂的用戶定義程序概念。
APOC庫(詳見https://github.com/neo4j-contrib/neo4j-apoc-procedures)是最強大和最受歡迎的Neo4j庫之一。 它包含許多算法(在編寫本文時大約514個),以幫助處理數據集成,圖形算法或數據轉換等領域的許多不同任務。 毫不奇怪,它還有幾個用於分析圖數據庫元數據的功能。要在Neo4j 3.x中啓用APOC,有幾個簡單的步驟:
(1)停止Neo4j服務
(2)將最新版本的APOC JAR文件下載並複製到數據庫下的plugins文件夾,例如graph.db \ plugins
(3)將以下行添加到neo4j.conf文件中:dbms.security.procedures.unrestricted = apoc. *
(4)再次啓動Neo4j服務
用於分析的開箱即用功能都在apoc.meta下,以下是一些示例:
6.1元數據
輸入:
CALL apoc.meta.data()
輸出:
結果分析:這將列出所有節點和關係以及每個節點的屬性,也就是元數據
6.2 模型展示
輸入:
CALL apoc.meta.graph()
等價於3.1
6.3 統計信息
輸入:
CALL apoc.meta.stats()
輸出:
6.4 元數據分析
輸入:
CALL apoc.meta.schema()
這將返回所有節點標籤,關係類型和屬性的元數據。
6.5 子集分析
輸入:
CALL apoc.meta.subGraph({labels:['Character'],rels:['INTERECTS']})
輸出:
結果分析:這是一個非常有用的函數,尤其適用於非常大的圖形,因爲它允許您分析節點和關係(子圖)的子集。
7. 深入探討
將數據存儲爲圖形具有巨大的優勢。圖形數據模型使我們能夠對大量數據的關係進行更強大的分析,並挖掘大量單個數據元素(節點)之間的隱藏連接。對與Neo4j這樣的圖形數據庫進行數據分析,可以讓我們更深入地瞭解我們正在處理的實際數據。然後,獲得的結果可用於進一步的詳細分析,性能調整,數據庫模式優化和數據遷移。
作爲本地圖形數據庫,Neo4j通過Cypher查詢語言提供本機圖形數據存儲和本機查詢處理。如本文所示,使用Cypher可以輕鬆完成一些最有用的數據分析任務。還有一些擴展支持更復雜和更先進的圖形分析;例如:中介中心性和連接組件。 Neo4j圖算法(詳見https://neo4j.com/docs/graph-algorithms/current/)是我用來執行更復雜的數據分析的算法。安裝後,可以直接調用這些函數作爲Cypher查詢的一部分,並在Neo4j瀏覽器中顯示結果。我打算在即將發表的文章中對此進行更多介紹。
參考:https://neo4j.com/blog/data-profiling-holistic-view-neo4j/
https://neo4j.com/blog/import-10m-stack-overflow-questions/