Spark 提供便捷的 readwrite 方法,搭配 org.neo4j.spark.DataSource 格式,方便讀寫 Neo4j 資料。利用 Cypher 查詢語言,能精確操作圖形資料,並將查詢結果轉換為 Spark DataFrame,便於後續分析。寫入 Neo4j 時,可選擇 SaveMode.ErrorIfExistsSaveMode.Overwrite 等模式,控制資料更新行為。整合 Apache Hop 等 ETL 工具,能簡化資料管道建置,並以低程式碼/無程式碼方式管理資料流,提升開發效率。Neo4j 圖形資料科學提供高效能演算法,應用於網路傳播、影響力分析、社群偵測、相似性計算和連結預測等場景。透過圖形投影,可選取特定圖形部分進行分析,並將結果寫回知識圖譜或輸出至下游系統。理解 Spark 與知識圖譜的資料模型對映關係,有助於最佳化資料轉換流程,並有效運用圖形資料科學的分析能力。

讀取 Neo4j 資料

要從 Neo4j 讀取資料,可以使用 Spark 的 read 方法,並指定 org.neo4j.spark.DataSource 作為格式。以下是範例程式碼:

val spark = SparkSession.builder().getOrCreate()

val df = spark.read
 .format("org.neo4j.spark.DataSource")
 .option("url", "bolt://localhost:7687")
 .option("query", "MATCH (n:Person)-[FOLLOWS]->(:Person {name:'emileifrem'}) WITH n LIMIT 20 RETURN id(n) AS id, n.name AS name")
 .load()

df.show()

這段程式碼會從 Neo4j 的 bolt 介面讀取資料,使用 Cypher 查詢語言來查詢 Person 節點及其關係。查詢結果會被轉換成 Spark 的 DataFrame。

寫入 Neo4j 資料

要將資料寫入 Neo4j,可以使用 Spark 的 write 方法,並指定 org.neo4j.spark.DataSource 作為格式。以下是範例程式碼:

import scala.util.Random

val spark = SparkSession.builder().getOrCreate()

import spark.implicits._

case class Person(name: String, surname: String, age: Int)

val ds = (
  // Populate the data source here
).toDS()

ds.write
 .format("org.neo4j.spark.DataSource")
 .mode(SaveMode.ErrorIfExists)
 .option("url", "bolt://localhost:7687")
 .option("labels", ":Person")
 .save()

這段程式碼會將 Spark 的 DataFrame 寫入 Neo4j 的 bolt 介面,使用 Person 節點及其屬性來建立新的節點。

內容解密:

在上面的範例程式碼中,我們使用了 Spark 的 readwrite 方法來讀取和寫入 Neo4j 的資料。這些方法提供了一種簡單且高效的方式來整合 Spark 和 Neo4j。透過使用 Cypher 查詢語言,可以輕鬆地查詢和建立圖形資料。

圖表翻譯:

  graph LR
    A[Spark] -->|read|> B[Neo4j]
    B -->|write|> A
    A -->|query|> C[Cypher]
    C -->|result|> B

這個圖表展示了 Spark 和 Neo4j 之間的整合過程。Spark 使用 read 方法從 Neo4j 讀取資料,然後使用 write 方法將資料寫入 Neo4j。Cypher 查詢語言被用來查詢和建立圖形資料。

將 Spark 資料寫入 Neo4j 知識圖

在將 Spark 資料寫入 Neo4j 知識圖的過程中,我們可以使用 Cypher 的模式來完成。以下是使用 Spark 和 Neo4j 的範例。

使用 Spark 將資料寫入 Neo4j

首先,我們需要建立一個 Spark Session,並載入我們想要寫入 Neo4j 的資料。然後,我們可以使用 write 方法將資料寫入 Neo4j。

val spark = SparkSession.builder().getOrCreate()
// 載入資料到 Spark DataFrame
val df =...
// 將資料寫入 Neo4j
df.write
 .format("org.neo4j.spark.DataSource")
 .option("relationship", "FOLLOWS")
 .option("relationship.source.labels", ":Person")
 .option("relationship.source.save.mode", "Overwrite")
 .option("relationship.source.node.keys", "source.name:name")
 .option("relationship.target.labels", ":Person")
 .option("relationship.target.save.mode", "Overwrite")
 .option("relationship.target.node.keys", "target.name:name")
 .save()

對應的 Cypher 程式碼

上述 Spark 程式碼對應的 Cypher 程式碼如下:

UNWIND $events AS event
MERGE (source:Person {name: event.source.name})
SET source = event.source
MERGE (target:Product {name: event.target.name})
SET target = event.target
CREATE (source)-[rel:FOLLOWS]->(target)
SET rel += event.rel

寫入模式選擇

在將資料寫入 Neo4j 時,我們需要選擇寫入模式。SaveMode.ErrorIfExists 會建立一個 CREATE 查詢,而 SaveMode.Overwrite 會建立一個 MERGE 查詢。

Spark 和知識圖之間的對映

Spark 的資料模型與知識圖的資料模型不同,因此在使用 Spark 分析或豐富知識圖時,我們需要管理兩者之間的對映。Spark 聯結器可以被視為一種管道,啟用使用者在兩個世界之間指定轉換,類別似於傳統的 ETL 工具,但在更低的抽象層次上。

內容解密:

在上述程式碼中,我們使用 write 方法將 Spark DataFrame 寫入 Neo4j。format 方法指定了資料來源為 Neo4j,option 方法指定了寫入 Neo4j 的相關引數,例如關係型別、節點標籤等。save 方法執行寫入操作。

圖表翻譯:

以下是上述程式碼的 Mermaid 圖表:

  flowchart TD
    A[Spark DataFrame] --> B[Write to Neo4j]
    B --> C[Specify relationship and node labels]
    C --> D[Set save mode and node keys]
    D --> E[Save to Neo4j]
    E --> F[Create relationship between nodes]

這個圖表展示了將 Spark DataFrame 寫入 Neo4j 的過程,包括指定關係和節點標籤、設定儲存模式和節點鍵、儲存到 Neo4j 以及建立節點之間的關係。

Apache Hop for ETL

Apache Hop是一種通用的ETL工具,能夠連線多種系統,包括知識圖和資料函式庫,提供低程式碼/無程式碼環境,以便於資料流的管道化。作為一種開源工具,Apache Hop具有良好的連線性,特別是在Neo4j知識圖的應用中。

ETL工具的選擇

作者對於ETL工具的選擇保持中立,建議使用企業標準的ETL工具,如果沒有企業標準,則可以考慮使用開源或雲端工具,如AWS Glue、Cloud ETL等。

Apache Hop的工作流程

Apache Hop提供了一個低程式碼/無程式碼環境,用於管道化資料流。例如,在Figure 5-10中,可以看到如何組態Apache Hop來:

  • 檢查系統可用性
  • 設定知識圖索引和約束
  • 清理從維基百科匯入的資料
  • 執行匯入工作到知識圖

對映和資料流

在Apache Hop中,可以組態對映從源資料系統到知識圖(或反之)。這通常是低程式碼/無程式碼的,例如在Figure 5-11中所示。

Cypher查詢和引數化

Apache Hop還允許指定Cypher查詢來執行知識圖的匯入和匯出。可以提供引數化的Cypher查詢,並使用UI工具對映資料到這些引數。執行時,Apache Hop繫結值到這些引數並執行Cypher查詢來載入資料到知識圖或從知識圖中檢索資料。

章節轉換

接下來,我們將轉換到第6章,探討知識圖的資料科學應用,包括圖演算法和Neo4j Graph Data Science。這些內容將幫助您瞭解如何使用圖演算法來處理知識圖並獲得可行的見解。

圖解資料科學中的圖表演算法

圖表演算法是資料科學中的一種重要工具,能夠幫助我們從圖表中提取有用的資訊。圖表演算法可以分為五大類別:網路傳播、影響力、社群偵測、相似性和連結預測。

網路傳播

網路傳播是指圖表中節點之間的訊號傳播。這種傳播可以用於瞭解疾病在社群中的傳播或供應鏈中的弱點。透過計算圖表中節點之間的距離和連線性,可以找出訊號傳播的路徑,並且可以用於最佳化訊號傳播的效率。

內容解密:

網路傳播演算法可以用於計算圖表中節點之間的距離和連線性。這種計算可以用於找出訊號傳播的路徑,並且可以用於最佳化訊號傳播的效率。例如,在社交網路中,網路傳播演算法可以用於找出影響力最大的人物,並且可以用於最佳化廣告的投放。

影響力

影響力是指圖表中節點對其他節點的影響力。影響力大的節點可以作為橋樑和瓶頸,將訊號傳播到其他節點。影響力的計算可以用於找出圖表中最重要的節點,並且可以用於最佳化訊號傳播的效率。

內容解密:

影響力演算法可以用於計算圖表中節點的影響力。這種計算可以用於找出圖表中最重要的節點,並且可以用於最佳化訊號傳播的效率。例如,在社交網路中,影響力演算法可以用於找出影響力最大的人物,並且可以用於最佳化廣告的投放。

社群偵測

社群偵測是指圖表中節點之間的社群結構。社群偵測演算法可以用於找出圖表中緊密連線的社群,並且可以用於瞭解社群中的關係。

內容解密:

社群偵測演算法可以用於計算圖表中節點之間的社群結構。這種計算可以用於找出圖表中緊密連線的社群,並且可以用於瞭解社群中的關係。例如,在社交網路中,社群偵測演算法可以用於找出使用者之間的社群結構,並且可以用於最佳化廣告的投放。

相似性

相似性是指圖表中節點之間的相似度。相似性演算法可以用於找出圖表中相似的節點,並且可以用於瞭解節點之間的關係。

內容解密:

相似性演算法可以用於計算圖表中節點之間的相似度。這種計算可以用於找出圖表中相似的節點,並且可以用於瞭解節點之間的關係。例如,在推薦系統中,相似性演算法可以用於找出使用者之間的相似度,並且可以用於最佳化推薦的效率。

連結預測

連結預測是指圖表中節點之間的連結預測。連結預測演算法可以用於找出圖表中可能存在的連結,並且可以用於最佳化連結的建立。

內容解密:

連結預測演算法可以用於計算圖表中節點之間的連結預測。這種計算可以用於找出圖表中可能存在的連結,並且可以用於最佳化連結的建立。例如,在社交網路中,連結預測演算法可以用於找出使用者之間可能存在的連結,並且可以用於最佳化廣告的投放。

  graph TD
    A[網路傳播] --> B[影響力]
    B --> C[社群偵測]
    C --> D[相似性]
    D --> E[連結預測]

圖表翻譯:

上述圖表展示了五大類別圖表演算法之間的關係。網路傳播演算法可以用於找出訊號傳播的路徑,影響力演算法可以用於找出最重要的節點,社群偵測演算法可以用於找出緊密連線的社群,相似性演算法可以用於找出相似的節點,連結預測演算法可以用於找出可能存在的連結。這些演算法可以用於最佳化訊號傳播、廣告投放、推薦系統等應用。

圖形資料科學與知識圖譜

Neo4j 圖形資料科學是一種高度最佳化的 CPU 和 RAM 解決方案,提供最佳的效能和廣泛的演算法支援,無需特殊硬體。它通常比根據 GPU 的解決方案更快,因為並非所有圖形演算法都可以被表達為線性代數問題,而這些問題正是 GPU 可以高效執行的。

圖形資料科學的工作原理

Neo4j 圖形資料科學提供了一系列高效能、平行化的演算法,讓使用者可以根據需要選擇合適的演算法,並使用 Cypher 程式呼叫來執行。圖形資料科學的工作流程包括四個階段:

  1. 讀取投影圖: 選擇感興趣的圖形部分,並建立一個投影。這可以是一個子圖、特定的標籤和關係型別、Cypher 查詢模式或整個知識圖譜。
  2. 載入投影圖: 將圖形投影匯出到一個緊湊的、記憶體中的格式,準備進行平行處理。
  3. 執行演算法: 執行選定的演算法,使用所選引數。
  4. 儲存結果: 將結果寫回知識圖譜(例如,豐富節點)或計算結果,以便傳送到下游系統或呼叫使用者。

縮放圖形演算法

圖形投影階段將知識圖譜(或其部分)載入主記憶體中,以壓縮格式。這保證了高效能,因為區域性性優勢使得存取更快。然而,對於非常大的圖形,您可能需要增加 RAM 來支援。對於平行演算法,您還可以增加 CPU 核心數量。

分散式圖形處理

雖然增加 CPU 核心和 RAM 似乎是一種簡單的解決方案,但它會導致非均勻架構,其中任何節點的鄰居可能位於遠端伺服器上,存取時間遠大於本地記憶體。實際上,分散式圖形處理效率低下,因為缺乏單個大記憶體空間的區域性性優勢。相反,指標解參照變成了網路操作。

示例:執行圖形資料科學

以下示例展示瞭如何使用 Cypher 執行圖形資料科學,豐富知識圖譜。這裡,我們投影了一個社交網路,包含 Person 節點和 FRIEND 關係,然後執行了一個 betweenness 中央性演算法,以計算最具影響力的個人。

CALL gds.graph.project.cypher(
  'gds-example-graph',
  'MATCH (p:Person) RETURN id(p) AS id',
  'MATCH (p1:Person)-[:FRIEND]->(p2:Person) RETURN id(p1) AS source, id(p2) AS target, "FRIEND" AS type'
);

CALL gds.betweenness.write('gds-example-graph', { writeProperty: 'betweennessCentrality' });

這個查詢包含四個關鍵元素:

  1. 命名圖形投影: 在這裡,它是 gds-example-graph,這個投影將被儲存在圖形目錄中,以便於存取。
  2. 節點查詢: 選擇要包含在投影中的節點。Neo4j 圖形資料科學提供了多種方法,包括使用 Cypher 投影來指定選擇節點的 Cypher 程式碼。
  3. 關係查詢: 選擇要包含在投影中的關係。
  4. 執行演算法: 執行 betweenness 中央性演算法,並將結果寫回知識圖譜。

圖表翻譯:

  flowchart TD
    A[讀取投影圖] --> B[載入投影圖]
    B --> C[執行演算法]
    C --> D[儲存結果]

這個流程圖展示了圖形資料科學的工作流程,從讀取投影圖到儲存結果。每一步驟都對應於一個特定的操作,保證了高效和正確的執行。

圖形資料科學簡介

圖形資料科學是一種利用圖形結構和演算法來分析和理解複雜資料的方法。Neo4j 是一種流行的圖形資料函式庫,提供了強大的圖形資料科學工具。

節點投影和關係查詢

在圖形資料科學中,節點投影和關係查詢是兩個重要的概念。節點投影是指選擇要包含在圖形中的節點,而關係查詢是指選擇要包含在圖形中的關係。

中介中心性演算法

中介中心性演算法是一種用於計算節點在圖形中的重要性的演算法。它根據節點之間的最短路徑數量來計算節點的重要性。

實驗工具

Neo4j 提供了多種工具來支援圖形資料科學實驗,包括 Python 驅動程式和 Jupyter Notebook。

資料載入

資料載入是圖形資料科學中的第一步。可以使用 CSV 檔案或其他格式來載入資料。

節點投影

LOAD CSV WITH HEADERS FROM "nr-stations-all.csv" AS station
CREATE (:Station {name: station.name, crs: station.crs})

關係查詢

LOAD CSV WITH HEADERS FROM "nr-station-links.csv" AS link
MATCH (s:Station {crs: link.source})
MATCH (t:Station {crs: link.target})
CREATE (s)-[:LINK {weight: link.weight}]->(t)

中介中心性演算法

from graphdatascience import GraphDataScience

# 連線到資料函式庫
host = "bolt://127.0.0.1:7687"
user = "neo4j"
password = "yolo"
gds = GraphDataScience(host, auth=(user, password), database="neo4j")

# 執行中介中心性演算法
gds.run_cypher("""
    CALL gds.betweenness.write({
        graphName: 'rail-network',
        nodeProjection: 'Station',
        relationshipProjection: 'LINK'
    })
    YIELD nodeId, centrality
    RETURN nodeId, centrality
""")

內容解密:

上述程式碼使用 Cypher 查詢語言來載入資料、建立節點和關係,並執行中介中心性演算法。中介中心性演算法根據節點之間的最短路徑數量來計算節點的重要性。

圖表翻譯:

此圖表展示了中介中心性演算法的結果。每個節點的大小代表其重要性,越大的節點代表越重要的節點。

  flowchart TD
    A[載入資料] --> B[建立節點和關係]
    B --> C[執行中介中心性演算法]
    C --> D[計算節點重要性]
    D --> E[顯示結果]

實驗工具

Neo4j 提供了多種工具來支援圖形資料科學實驗,包括 Python 驅動程式和 Jupyter Notebook。這些工具可以幫助使用者快速地實驗和分析圖形資料。

載入車站間軌道關係

為了在圖資料函式庫中建立車站間的軌道關係,我們可以使用 Cypher 查詢語言。以下是載入軌道關係的 Python 程式碼:

gds.run_cypher("""
    LOAD CSV WITH HEADERS FROM "nr-station-links.csv" AS track
    MATCH (from:Station {crs: track.from})
    MATCH (to:Station {crs: track.to})
    MERGE (from)-[:TRACK {distance: round(toFloat(track.distance), 2)}]->(to)
""")

這段程式碼做了三件事:

  1. 連線到資料函式庫:建立一個 GraphDataScience 類別的例項,以便存取圖資料函式庫。
  2. 載入車站節點:使用 gds.run_cypher 方法執行 Cypher 查詢,載入車站節點到圖資料函式庫中。
  3. 建立軌道關係:使用 gds.run_cypher 方法執行 Cypher 查詢,建立車站間的軌道關係,並將距離屬性加入關係中。

建立圖投影

為了執行圖演算法,我們需要建立一個圖投影。圖投影是一個記憶體中的圖,適合用於演算法計算。以下是建立圖投影的 Python 程式碼:

from graphdatascience import GraphDataScience

# 建立圖投影
gds = GraphDataScience()
projection = gds.graph_project(
    "railway",
    ["Station"],
    ["TRACK"]
)

這段程式碼建立了一個名為 “railway” 的圖投影,包含 “Station” 節點和 “TRACK” 關係。

執行圖演算法

現在,我們可以使用圖投影執行圖演算法。例如,我們可以使用 Dijkstra 演算法找出兩個車站間的最短路徑。以下是執行 Dijkstra 演算法的 Python 程式碼:

from graphdatascience import GraphDataScience

# 執行 Dijkstra 演算法
result = gds.algorithms.shortestPaths.dijkstra(
    projection,
    "Station",
    "TRACK",
    "distance"
)

這段程式碼執行 Dijkstra 演算法,找出兩個車站間的最短路徑,並將結果存放在 result 變數中。

圖表翻譯:

  graph LR
    A[載入車站節點] --> B[建立軌道關係]
    B --> C[建立圖投影]
    C --> D[執行圖演算法]
    D --> E[取得結果]

這個流程圖描述了載入車站節點、建立軌道關係、建立圖投影、執行圖演算法和取得結果的過程。

使用 Graph Data Science 實作路徑查詢

在本文中,我們將探討如何使用 Graph Data Science 實作路徑查詢。首先,我們需要建立一個 GraphDataScience 物件,以便連線到 Neo4j 資料函式庫。

host = "bolt://127.0.0.1:7687"
user = "neo4j"
password = "yolo"
gds = GraphDataScience(host, auth=(user, password), database="neo4j")

接下來,我們需要定義一個投影(projection),以便指定要查詢的路徑。投影是透過 Cypher 查詢語言定義的。在這個例子中,我們定義了一個名為 trains 的投影,包含所有車站和軌道之間的關係。

gds.graph.project.cypher(
    graph_name='trains',
    node_spec='MATCH (s:Station) RETURN id(s) AS id',
    relationship_spec="""
        MATCH (s1:Station)-[t:TRACK]->(s2:Station)
        RETURN id(s1) AS source, id(s2) AS target, t.distance AS distance
    """
)

定義好投影後,我們就可以使用 Graph Data Science 的 API 來查詢路徑。例如,我們可以使用 Dijkstra 演算法來查詢兩個車站之間的最短路徑。

from graphdatascience import GraphDataScience

# 定義起點和終點車站
bham = gds.find_node_id(["Station"], {"name": "Birmingham New Street"})
eboro = gds.find_node_id(["Station"], {"name": "Edinburgh"})

# 執行 Dijkstra 演算法
result = gds.algorithms.shortestPaths.dijkstra(
    graph_name='trains',
    sourceNode=bham,
    destinationNode=eboro,
    relationshipWeightProperty='distance'
)

# 輸出結果
print(result)

這個例子展示瞭如何使用 Graph Data Science 來查詢兩個車站之間的最短路徑。透過定義投影和使用 Dijkstra 演算法,我們可以輕鬆地查詢路徑,並得到最短路徑的結果。

圖表翻譯:

  flowchart TD
    A[定義投影] --> B[執行 Dijkstra 演算法]
    B --> C[輸出結果]
    C --> D[結束]

內容解密:

在這個例子中,我們使用 Graph Data Science 來查詢兩個車站之間的最短路徑。首先,我們定義了一個投影,包含所有車站和軌道之間的關係。接下來,我們使用 Dijkstra 演算法來查詢路徑,並得到最短路徑的結果。這個例子展示瞭如何使用 Graph Data Science 來解決實際問題,並得到有用的結果。

使用 Graph Data Science 進行鐵路網路分析

在本文中,我們將使用 Graph Data Science 進行鐵路網路分析,計算各個車站的中心性,並找出對鐵路網路影響最大 的車站。

使用 Dijkstra 演算法計算最短路徑

首先,我們使用 Dijkstra 演算法計算 Birmingham New Street 和 Edinburgh 之間的最短路徑。

shortest_path = gds.shortestPath.dijkstra.stream(
    gds.graph.get("trains"),
    sourceNode=bham,
    targetNode=eboro,
    relationshipWeightProperty="distance"
)
print("Shortest distance: %s" % shortest_path.get('costs').get(0)[-1])

結果顯示,Birmingham New Street 和 Edinburgh 之間的最短距離為 298.0。

計算車站中心性

接下來,我們計算各個車站的中心性,使用 betweenness centrality 演算法。

result = gds.betweenness.stream(graph)
highest_score = result.sort_values(by="score", ascending=False).iloc[0:1].get('nodeId')
n = gds.run_cypher(f"MATCH (s:Station) WHERE ID(s) = {int(highest_score)} RETURN s.name")
print("Station with highest centrality: %s" % n["s.name"][0])

結果顯示,Tamworth 車站具有最高的中心性,中心性分數為 1,967,643,而 Birmingham New Street 的中心性分數為 254,706,遠低於 Tamworth。

分析結果

雖然 Birmingham New Street 是英國第八繁忙的車站,但其中心性分數卻遠低於 Tamworth。這可能是因為中心性計算只考慮了連線的軌道,而沒有考慮乘客數量或列車路線。另一方面,Tamworth 的高中心性可能是因為其地理位置,使得其成為鐵路網路中的重要節點。

從技術架構視角來看,整合 Spark 和 Neo4j 擴充套件了資料處理和分析的可能性,尤其是在處理圖資料方面。本文深入探討瞭如何利用 Spark 讀取和寫入 Neo4j 資料,並運用 Cypher 語法進行高效的圖形資料操作。分析段落中,我們比較了不同寫入模式(ErrorIfExistsOverwrite)的差異,並闡述了 Spark 和知識圖譜之間的對映關係,強調了資料轉換的重要性,如同傳統 ETL 工具。然而,直接使用 Spark 處理大規模圖資料仍存在效能瓶頸。本文也探討了 Apache Hop 作為低程式碼/無程式碼 ETL 工具的優勢,及其在知識圖譜構建和資料管道化方面的應用,包括系統可用性檢查、索引與約束設定、資料清理以及匯入知識圖譜等流程。此外,文章還介紹了圖演算法在資料科學中的應用,涵蓋網路傳播、影響力、社群偵測、相似性和連結預測等五大類別,並以 Mermaid 圖表清晰地展示了這些演算法之間的關係。最後,本文詳細闡述了 Neo4j 圖形資料科學的優勢、工作原理以及如何利用 Cypher 查詢進行圖形投影、演算法執行和結果儲存。雖然 Neo4j 圖形資料科學提供高效的圖形處理能力,但對於超大規模圖形,分散式處理的挑戰依然存在。展望未來,圖形資料函式庫與大資料處理框架的整合將持續發展,更有效率的分散式圖形演算法和更友善的工具將會出現,進一步降低圖形資料科學的應用門檻。玄貓認為,結合 Spark 和 Neo4j 的圖形資料處理方案,在特定領域,例如社交網路分析、推薦系統和知識圖譜構建等,具有顯著的應用價值,值得技術團隊深入研究和應用。