Alec
Alec

Reputation: 2752

How to get-or-create a unique child node in Neo4j

I'm new to Neo4j, and playing around by trying to set up a music database. To start simple, I'm just playing with two labels:

Obviously this is a parent-child relationship, where a Song is a child of an Artist (or possibly multiple Artists), and might look something like:

(:Artist {name:'name'})-[:RECORDED]->(:Song {title:'title'})

I am making the following assumptions:

To give an example of what I'd like to do:

  1. I ingest "Hallelujah" by Leonard Cohen. A new Artist node and Song node are created, with a RECORDED relationship
  2. I ingest "Hallelujah" by Jeff Buckley. Again, new Artist and Song node are created, with a RECORDED relationship. The first "Hallelujah" Song is not associated with this new graph at all.
  3. I ingest "Hallelujah" by Jeff Buckley again. Nothing happens.
  4. I ingest "Lilac Wine" by Jeff Buckley. We reuse our old Artist node, but I have a new Song node with a RECORDED relationship

From what I can tell, using MERGE gets me close, but not quite there (it stops duplication of the ARTIST, but not of the SONG). If I use CREATE, then point number 3. doesn't work properly.

I guess I could add another property to the SONG label which tracks its ARTIST (and I can therefore make unique), but that seems a little redundant and unidiomatic of a graph database, no?

Does anyone have any bright ideas on the most succinct way of enforcing these relationships and requirements?

Upvotes: 0

Views: 244

Answers (2)

stdob--
stdob--

Reputation: 29172

Merge Artist first, and after Song:

WITH 'Leonard Cohen' AS ArtistName, 
     'Hallelujah'    AS SongTitle
MERGE (A:Artist {name:ArtistName})
WITH A, 
     SongTitle 
OPTIONAL MATCH p=(A)-[:RECORDED]->(:Song {title:SongTitle})
FOREACH (x in CASE WHEN p IS NULL THEN [1] ELSE [] END |
  CREATE (S:Song {title:SongTitle})
  MERGE (A)-[:RECORDED]->(S)
) 
WITH A, 
     SongTitle
MATCH p = (A)-[:RECORDED]->(:Song {title:SongTitle})
RETURN p

Upvotes: 1

InverseFalcon
InverseFalcon

Reputation: 30397

I don't think song title is something you can rely on for uniqueness, especially if this graph includes covers of existing songs.

Determining some additional means to imply uniqueness is the way to go.

Artist is one way. Recorded date might be another piece of data to consider. If you're reading this from some other kind of database, there may be some other unique ID they use for uniqueness.

Whatever the case, once you have the fields that you want to use to determine uniqueness, MERGE your song node with all those fields present.

Upvotes: 0

Related Questions