数据建模
将数据从 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)
图模型。
规范化加载方法要求您创建多个不同的 DataFrames:一个用于您所需图中的每个节点标签和关系类型。例如,在这种情况下,您可能会创建三个 DataFrames
-
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")
一旦这些简单的 DataFrames 代表了'标签表的规范视图'(即,每个节点标签或关系类型一个 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;
一个更好的 Cypher 查询,它会导致一个更干净的 DataFrame,如下所示
MATCH path=(p:Person { name: "Andrea" })-[r:KNOWS*]->(o:Person)
RETURN length(path) as pathLength, p.name as p1Name, o.name as p2Name