数据建模
将数据从 DataFrames 转换为图
当获取任何复杂的 DataFrames 集并准备将其加载到 Neo4j 中时,您有两种选择
-
规范化加载
-
Cypher® 解构
本节将对这两种方法进行介绍,并提供从性能和复杂性角度来看的优势和潜在缺点的信息。
在可能的情况下,使用规范化加载方法以获得最佳性能和可维护性。 |
规范化加载
假设您希望将一个名为 purchases
的 DataFrame 加载到 Neo4j 中,内容如下
product_id,product,customer_id,customer,quantity
1,Socks,10,David,2
2,Pants,11,Andrea,1
此数据表示一个简单的 (:Customer)-[:BOUGHT]→(:Product)
图模型。
规范化加载方法要求您创建多个不同的 DataFrame:您的目标图中的每个节点标签和关系类型对应一个 DataFrame。例如,在这种情况下,您可以创建三个 DataFrame
-
val products = spark.sql("SELECT product_id, product FROM purchases")
-
val customers = spark.sql("SELECT customer_id, customer FROM purchases")
-
val bought = spark.sql("SELECT product_id, customer_id, quantity FROM purchases")
一旦这些简单的 DataFrame 表示了“标签表”的规范化视图(即,每个节点标签或关系类型对应一个 DataFrame/表),那么连接器提供的用于写入节点和关系的现有实用程序就可以使用,而无需额外的 Cypher。此外,如果这些框架通过标识符变得唯一,那么数据就已经为最大并行性做好了准备。(请参阅以下章节中的并行性说明。)
Cypher 解构
Cypher 解构是使用单个 Cypher 语句将复杂记录处理成完整图模式的过程。让我们再次看看数据示例
product_id,product,customer_id,customer,quantity
1,Socks,10,David,2
2,Pants,11,Andrea,1
要将此数据存储在 Neo4j 中,您可以使用如下 Cypher 查询
MERGE (p:Product { id: event.product_id })
ON CREATE SET p.name = event.product
WITH p
MERGE (c:Customer { id: event.customer_id })
ON CREATE SET c.name = event.customer
MERGE (c)-[:BOUGHT { quantity: event.quantity }]->(p);
在这种情况下,整个工作可以通过单个 Cypher 语句完成。随着 DataFrames 变得复杂,Cypher 语句也会变得相当复杂。
将数据从图转换回 DataFrames
通常,始终使用显式 RETURN 语句并解构您的结果。
|
一种常见模式是编写复杂的 Cypher 语句(可能遍历许多关系)以将数据集返回到 Spark。由于 Spark 不理解图原语,因此在 Spark 中表示原始节点、关系或路径的方法并不多。因此,强烈建议不要将这些类型从 Cypher 返回到 Spark,而是专注于具体属性值和函数结果,您可以在 Spark 中将其表示为简单类型。
例如,以下 Cypher 查询会产生一个难以操作的笨拙 DataFrame
MATCH path=(p:Person { name: "Andrea" })-[r:KNOWS*]->(o:Person)
RETURN path;
一个生成更清晰 DataFrame 的更好 Cypher 查询如下
MATCH path=(p:Person { name: "Andrea" })-[r:KNOWS*]->(o:Person)
RETURN length(path) as pathLength, p.name as p1Name, o.name as p2Name