从 V(1) 与 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 循环中的属性
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. 对每个教师和学生表执行相同的操作。

  2. 对请求者信息运行 MySQL 联接,以从"报告"表中查找按类分组的链接值。

$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')
");
}

此模式适用于少量记录,在这些记录中,我将能够拥有一组小型的、定义明确的交互。但是,由于报告记录的顶点已经带有其链接信息,我想知道是否有办法简化此过程。我理想的工作流程如下:

  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 驱动程序允许对 Gremlin 脚本进行参数化。我强烈建议您调整代码以利用该功能。它将大大提高性能。

最新更新