I am curious if there's a way to copy a subgraph by using Gremlin traversals only. Here's an illustration of the problem. I'd like to copy the block on the left side
The block on the left is the original data, which I'm calling source data in the code. I'm looking for a traversal that copies the source branch with its attached namespaces, types and the attributes attached to the types.
The image show the labels of the elements. Further more, all elements have properties that are globally unique (e.g. "id") and properties that are unique within the branch and therefore are copied to the other branch (e.g. "code").
I found this post that layed out how to copy a vertex and its edges to and form other source vertices. From that I figured out how to copy all vertices and edges from to the namespaces and from the types.
First I'm copying the source branch.
g.V().has("uuid", sourceId.toString()).as("source")
/**
* Copy source branch
*/
.addV(select("source").label()).as("copy")
.sideEffect(
select("source").properties().as("p")
.select("copy")
.property(select("p").key(), select("p").value()) // copy all properties to new vertex
.property("uuid", copiedId)
.property("_createdBy", modifier)
.property("_creationDate", transactionDate)
.property("_lastUpdatedBy", modifier)
.property("_lastUpdateDate", transactionDate)
)
.next();
Here I'm copying the namespaces, hasNamespace edges, types, hasBranch edges and attributes.
g.V().has("uuid", sourceId.toString()).as("source")
.addE("hasCopy")
.to(V().has("uuid",copiedId))
.inV().as("copy")
/**
* copy hasNamespace edges - from branch (source) to namespace
*
*/
.sideEffect(
select("source")
.outE("hasNamespace").as("e")
.inV().as("namespace_source")
.addV(select("namespace_source").label()).as("namespace_copy") // create clone vertices and remember them
.property("_lastUpdatedBy", modifier)
.addE(select("e").label()).as("e_copy")
.from(select("copy"))
.to(select("namespace_copy"))
.select("e").properties().as("p")
.select("e_copy")
.property(select("p").key(), select("p").value())
.property("_createdBy", modifier) // manually update properties
)
/**
* copy branches and hasBranch edges
*/
.sideEffect(
select("source")
.inE("hasBranch").as("e")
.outV().as("type_source")
.addV(select("type_source").label()).as("type_copy")
.property("_lastUpdatedBy", modifier)
.addE("hasBranch").as("e_copy")
.to(select("copy"))
.select("e").properties().as("p")
.select("e_copy")
.property(select("p").key(), select("p").value())
.property("_createdBy", modifier) // update properties
)
/**
* copy attribute vertices
*/
.sideEffect(
select("source")
.in("hasBranch").out("hasAttribute").as("attribute_source") // select and remember types
.addV(select("attribute_source").label()).as("attribute_copy") // create clone vertices and remember them
.select("attribute_source").properties().as("p") // select properties of the attribute
.select("attribute_copy") // select copied namespaces
.property(select("p").key(), select("p").value()) // insert the copied properties
.property("_createdBy", modifier) // update properties
).next();
My assumption is that adding the hasAttribute edges, in a similar way, through a traversal (e.g. without returning lists of hasAttribute edges, attributes, and types and matching them based on properties) would be the most efficient way to copy these elements, but I'm not sure how to do that. Thanks in advance for your help.
I'm using Janusgraph.