Контекст:
У меня есть граф примерно с 2000 вершинами и 6000 ребрами, со временем он может вырасти до 10000 вершин и 100000 ребер. В настоящее время я добавляю новые вершины, используя следующий запрос обхода:
Добавление вершин и краев
queryVertex = "g.V().has(label, name, foo).fold().coalesce(
unfold(), addV(label).property(name, foo).property(model, 2)
).property(model, 2)"
Намерение здесь состоит в том, чтобы найти вершину с именем foo и, если она найдена, обновить ее свойство model
, в противном случае создать новую вершину и установить свойство model
. это выдается дважды: один раз для исходной вершины, а затем для целевой вершины.
После создания двух связанных вершин выдается другой запрос для создания ребра между ними:
queryEdge = "g.V('id_of_source_vertex').coalesce(
outE(edge_label).filter(inV().hasId('id_of_target_vertex')),
addE(edge_label).to(V('id_of_target_vertex'))
).property(model, 2)"
здесь, если между двумя вершинами есть ребро, свойство model
на ребре обновляется, в противном случае оно создает ребро между ними.
И псевдокод, который это делает, выглядит следующим образом:
for each edge in the list of new edges:
//upsert source and target vertices:
execute queryVertex for edge.source
execute queryVertex for edge.target
// upsert edge:
execute queryEdge
Это работает, но крайне неэффективно; например, для указанного размера графика для завершения требуется несколько минут, а при некотором параллелизме внутри приложения это сокращает время всего на пару минут. Конечно, для такого маленького размера графа должен быть более эффективный способ сделать это.
Вопрос
* Как сделать эти апсерты быстрее?