Reputation: 787
I'm creating a very basic versioning system for my nodes in my database. What I want to do is when there is an edit:
(oldreplica)-[:IsPreviousVersionOf]->(replica)
(oldreplica)-[:IsPreviousVersionOf]->(node)
(replica)-[:IsPreviousVersionOf]->(node)
This way I don't have to touch any of the relationships the node has. Every query I write ends up with the node and replica having the same content.
Is there a way to do this, or do I need to write two queries?
Upvotes: 3
Views: 1346
Reputation: 787
Okay, I've figured it out!
// Find the editable Node
MATCH (mainNode)-[:HasInternal]->(:EditableUuid{uuid:'2828b80b-e3d8-478e-ad31-b791b4e8d318'})
// Create a copy and copy the contents
CREATE (copy:Content)
SET copy = mainNode
// Create a new subquery so that we don't set the contents of both copy and mainNode
WITH mainNode, copy
// Increment the version number on the mainNode
SET mainNode.version = mainNode.version + 1
// Connect replica to the mainNode
MERGE (copy)-[:IsPreviousVersionOf]->(mainNode)
// Create a new subquery where we change the links of any old versions
with mainNode, copy, copy.version - 1 as oldversion
// Find older versions and connect them to the copy
MATCH (oldreplica:Content{version:oldversion})-[oldRel:IsPreviousVersionOf]->(mainNode)
MERGE (oldreplica)-[:IsPreviousVersionOf]->(copy)
// Delete the old relationship of the nodes
DELETE oldRel
This way the 'newest' version is always the one that already has the links and the old ones are just copies of that one in time.
Upvotes: 1
Reputation: 18002
You can do this all in one query; I think the two pieces you're missing are how to copy the node in the first place, and how to "join" subqueries using the WITH
keyword. Here's an example. You should triple-check this query, because your terminology and relationship shifting is tricky, so please verify carefully this is what you want.
The WITH
blocks here bind certain matched nodes to variables which you can use in subsequent queries. In this way we can carry over the results of one query into another. The other bit is that nodes are just maps of their properties, so you can "copy" a node by setting one map to another.
MATCH (node:Content{version:1})
WITH node as oldNode
CREATE (copy:Cotent)
SET copy=oldNode
WITH oldNode, copy
MATCH (oldreplica:Content{version:0})
MERGE (oldNode)-[:IsPreviousVersionOf]->(copy)
MERGE (oldreplica)-[oldRel:IsPreviousVersionOf]->(copy)
DELETE oldRel
WITH copy, oldNode
MERGE (copy)-[:IsPreviousVersionOf]->(oldNode)
MERGE (oldreplica)-[:IsPreviousVersionOf]->(copy);
Upvotes: 1