从 V(1) 与 V(any) 的 属性 匹配的所有顶点添加边

Add Edge from all Vertices where V(1) matches property of V(any)

我正在将 MySql 中的现有数据集导入 Gremlin-Server,并且我在 MySQL 数据库中存储了特定的关系模式,我正在努力导入。

模式示例如下:我们有 StudentsTeachersReports。为简单起见,架构将如下所示:

+------------+--------------+
| student_id | student_name |
+------------+--------------+
| 1          | Albert       |
+------------+--------------+

+------------+--------------+
| teacher_id | teacher_name |
+------------+--------------+
| 1          | Bartolo      |
+------------+--------------+

+------------+--------------+----------------+------------------+
| report_id  | report_name  | requester_type | requester_forid  |
+------------+--------------+----------------+------------------+
| 1          | grade_lookup | student        | 1                |
+------------+--------------+----------------+------------------+
| 2          | attendees    | teacher        | 1                |
+------------+--------------+----------------+------------------+

充分理解这是糟糕的 MySQL 最佳实践(我们进行此迁移的部分原因),我一直在执行数据导入。目前它 运行 的模式是:

  1. 将所有“报告”作为顶点导入 Gremlin,并将字段名称映射到 PHP 循环
  2. 中的属性
foreach($reports as $report) {
    $gremlin->send("
        g.V().addV('Report')
        .property('report_id', '" . $report['report_id'] . "')
        .property('fortype','" . $report['requester_fortype'] . "')
        .property('forid', '" . $report['requester_forId'] . "')
    ");
}
  1. 对每个教师和学生 table 执行相同的操作。

  2. 运行 a MySQL 加入请求者信息以从“报告”中查找 linked 值,按 class 分组table.

$query = "
SELECT report_id, requester_type, requester_forid 
FROM report 
WHERE requester_type = 'student' 
JOIN student ON requester_forid = requester_type;
";
$rows = mysqli_query($query);
foreach($rows as $row){
   # Upsert Gremlin Edge between the objects by coalescing the vertices
   $gremlin->send("
        g.V().has('Report', 'report_id', '". $row['report_id'] ."').as('fromRecord').
        V().has('Student', student_id, ".$row['requester_forid'].").
           coalesce(__.inE('report_for_student').where(outV().as('fromRecord')),
                    addE('report_for_student').from('fromRecord')
   ");
}

此模式适用于少量记录,我可以在其中进行一组小型的、定义明确的交互。然而,由于报告记录的顶点已经携带了它们的 link 信息,我想知道是否有办法简化这个过程。我理想的工作流程如下:

  1. 导入所有顶点
  2. 对于 属性 与 _type 匹配的任何一个,向与“类型”字段的标签与“id”相匹配的顶点添加出边 属性

我这里的尝试是

g.V().has('requester_type').values('requester_type').store('rt')
.sideEffect(V().has('rt')).addE('is_fortype').from('rt')

但这会将所有 'requester_type' 的边缘添加到所有边缘,并且没有进行我需要它进行的过滤。我有更好的方法来解决这个具体问题吗?我可以使用我的框架 运行 在一个循环中使用许多 upsert-edge 函数,或者我可以在属性匹配属性的地方插入边,使用每个参数的属性来通知连接及其方向。

对于加载数据,我通常建议您将源数据放入不会使您处于必须尝试在顶点上“连接”以构建边的情况下的形式。除非有适当的索引,否则迭代 V() 以构建这些连接的成本对于除最小图之外的任何东西都是昂贵的。当然,仅仅为此目的索引字段似乎是“错误的”,因为它创建的索引在负载之外没有实质性价值。在某些图表上,它甚至可能会以资源和加载时间为代价。

在你的第一种方法中减少你的负载以“加载所有顶点”和“加载所有边”对我来说似乎很好。如果这是从头开始的一次性批量加载,我不确定为什么需要使用 coalesce()。如果您的数据中存在某种您试图消除的重复项,那么我会在您查询源数据时这样做,并完全避免这种情况的发生。摆脱现有的边缘检查应该会提高加载速度。

如果您为顶点添加全局唯一标识符而不是尝试使用整数进行边缘加载,则可能会使边缘加载更加普遍和容易。那么边加载的逻辑就更直接了,不需要你的代码在加载边时推理顶点标签。然后,您还可以对数据进行预排序,然后构建您的 Gremlin 以批量加载单个顶点周围的边,这将有助于避免一遍又一遍地查找相同的顶点。

最后,我假设您使用的 PHP 驱动程序允许 parameterization 您的 Gremlin 脚本。我强烈建议您调整代码以利用该功能。它将大大提高性能。