Reputation: 2813
I have an application which dispatches database write commands via a message queue to workers (very high volume), so there is a no guarantee as to the order they will be received in.
I have two nodes, for example, "Account" and "Media". In this hypothetic application, a user can upload media anonymous, which automatically creates an account for them which they can then associate later.
Two messages, one for Account and one for Media will be received (almost certainly by different workers). Neither of them knows whether the other has been written yet. I need to write a query which will be run on each worker, which:
POSTED_BY
relationship between the twoTherefore, regardless of the order which each message is received in, the first query will create node A, and the second query will create node B + relationship.
If I was creating them both in the same query, it would be simple:
CREATE (m:Media { url: 'xyz.jpg' })-[:POSTED_BY]->(u:Account { username: 'johndoe' })
RETURN m,u
I've looked at CREATE UNIQUE
and MERGE
, however both seem to create the node if it doesn't exist, rather than just doing nothing.
Upvotes: 1
Views: 265
Reputation: 3677
I know the answer is already accepted, but don't feel like it actually answers the question, to wit:
If the other node does not exist, only create the current node
This can be achieved by the following:
CREATE (m:Media { url: 'xyz.jpg' })
WITH m
MATCH(u:Account { username: 'johndoe' })
CREATE(m)-[r:POSTED_BY]->(u)"
RETURN m
Unfortunately, this only returns m
if the match was successful.
Upvotes: 0
Reputation: 11216
I think you want to use MERGE
for this operation. Essentially, instead of creating one node at a time, you can create both nodes and the relationship but then update the particular node with additional properties.
Consider Message One is the media message
MERGE (m:Media { url: 'xyz.jpg' })
SET m =+ {media_props}
MERGE (u:Account { username: 'johndoe' })
MERGE (m)-[:POSTED_BY]->(u)
RETURN m
Consider Message Two is the new user account message
MERGE (u:Account { username: 'johndoe' })
SET u =+ {user_props}
MERGE (m:Media { url: 'xyz.jpg' })
MERGE (m)-[:POSTED_BY]->(u)
RETURN u
You could conceivably create each node separately via MERGE
and have a third message for the relationship. The pattern would be the same but would not set any additional properties on either of the nodes.
For example...
// message 1
// create the media node
MERGE (m:Media { url: 'xyz.jpg' })
SET m =+ {media_props}
RETURN m
// message 2
// create the user/account node
MERGE (u:Account { username: 'johndoe' })
SET u =+ {user_props}
// message 3
// create the relationship
MERGE (u:Account { username: 'johndoe' })
MERGE (m:Media { url: 'xyz.jpg' })
MERGE (m)-[r:POSTED_BY]->(u)
RETURN m,r,u
Note that all of the solutions assume that the key for identifying the media and the account in the merge statement are unique.
Upvotes: 1