背景
我们每分钟总共摄取 (500, 1500, 5000) (P25, P50, P75) 个顶点和边。每个顶点上大约有 5 个“记录”(id、label、3 个字符串属性),每条边上大约有 3 个“记录”(fromId、toId、label)。
当我们对 Neptune 进行 POC 时,我们没有将字符串属性添加到顶点。由于插入性能问题,经过反复试验,我们最终选择了这个解决方案:
void mergeVertices(final Collection<Vertex> vertices) {
List<Map<Object, Object>> maps = new ArrayList<>();
for (Vertex vertex : vertices) {
Map<Object, Object> map = new HashMap<>();
map.put(T.id, vertex.id());
map.put(T.label, vertex.label());
maps.add(map);
}
g.inject(maps).unfold().mergeV().iterate();
}
采用类似的方法更新插入边缘。然而,当我们通过 POC 阶段,并且想要开始向顶点添加属性时,我们将代码修改为如下所示:
void mergeVertices(final Collection<Vertex> vertices) {
List<Map<Object, Object>> maps = new ArrayList<>();
for (Vertex vertex : vertices) {
Map<Object, Object> map = new HashMap<>();
map.put(T.id, vertex.id());
map.put(T.label, vertex.label());
Map<String, Object> properties = vertex.properties();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
map.put(entry.getKey(), entry.getValue());
}
maps.add(map);
}
g.inject(maps).unfold().mergeV().iterate();
}
然后我们开始收到异常情况,具体来说:
{
"code":"ConstraintViolationException",
"requestId":"<elided>",
"detailedMessage":"Vertex with id already exists: ",
"message":"Vertex with id already exists: "
}
当我们恢复这些更改时,错误就消失了。我们在 TinkerPop Server 的本地部署上测试了 code-with-property-upsert,没有收到任何错误。
问题
我们如何才能有效地更新插入属性而不遇到这些错误?
我们采用
g.inject(maps)
方法的最初原因是,由于我们对该技术缺乏经验,因此我们很难在 Neptune 中获得良好的插入性能,即大约 30 - 60 秒的更新插入时间。 200 个“记录”。
读者须知:
“记录”是从 Neptune 文档借用的术语。
当您单独使用
mergeV()
时(不带任何参数),它会寻找 100% 完全匹配(包括属性)。 当它找到具有相同 ID 的另一个顶点时,就会产生约束冲突。 Neptune 中的少数限制之一是顶点或边的每个 ID 必须是唯一的。
您需要的是与顶点 ID 上的匹配进行合并。 这意味着您需要将 ID 包含在
mergeV()
中。
TinkerPop 文档中提供了一个这样做的示例,您可以在其中将 ID 作为单独的列表包含在地图中。 然后您展开
mergeV()
内地图中的第一个列表:
gremlin> g.inject([[(T.id):400],[(T.label):'Dog',name:'Pixel',age:1],[updated:'2022-02-1']]).
mergeV(limit(local,1)).
option(Merge.onCreate,range(local,1,2)).
option(Merge.onMatch,tail(local))
==>v[400]
找到匹配项后,您就可以决定在创建或匹配时执行哪些操作。 您需要包含这两个选项,因为不包含任何一个选项都无法对 id 进行匹配。
https://tinkerpop.apache.org/docs/current/reference/#mergevertex-step