Create relationship using if...else condition

Hi!

I'm very new to Neo4j. I have searched in the community and StackOverflow but I couldn't get the exact answer yet so posting it here. I am trying to create a relationship between 2 different node labels using 2 properties. Lets say my node labels are -

I:Inventory
O:Owners

Both I and O have common properties (p1 and p2). I want to be able to create a relationship (I) -[OWNED_BY]->(O) where I.p1 = O.p1 or I.p2 = O.p2.
The problem with this is it creates duplicate relationships for I when it has both p1 and p2 values. My requirement is to ignore I nodes when both p1 and p2 are null and then create only one relationship using either p1 or p2.

Thanks!

Hi @karthik.shetty,

Have you tried Merge instead of create while doing the relation?

H

Hello @karthik.shetty and welcome to the Neo4j community :slight_smile:

It will create the relation only where both properties are equal and when both exists that's to say when they are not null :slight_smile:

MATCH (I:Inventory) MATCH (O:Owners)
WHERE I.p1 = O.p1
AND I.p2 = O.p2
AND EXISTS(I.p1)
AND EXISTS(I.p2)
MERGE (I)-[OWNED_BY]->(O)

Regards,
Cobra

Thanks Cobra and Harold! I appreciate your response.

I did give this a try and it seems to be working for a small test set of data. Which is great!!!
BTW - I do have p1 and p2 in all the I:Inventory nodes but some of them are just null string (' '). So I slightly modified the query to this - please correct me if this doesn't look right

MATCH (I:Inventory) MATCH (O:Owners) WHERE I.p1 = O.p1 AND I.p2 = O.p2 AND I.p1 <> ' ' AND O.p2 <> ' ' MERGE (I)-[:OWNED_BY]->(O)

Also, the total Inventory nodes count would be in ~ 3 millions and I am looking at the solution to do it in batch wise so I am planning to use apoc.periodic.iterate like below. - please correct me if this is not the right approach.

CALL apoc.periodic.iterate("MATCH (I:Inventory) MATCH (O:Owners) WHERE I.p1 = O.p1 AND I.p2 = O.p2 AND I.p1 <> ' ' AND O.p2 <> ' ' RETURN I, O","MERGE (I)-[:OWNED_BY]->(O)",{batchSize:10000, parallel:false})

Thanks in advance!

You are right, I didn't know your database was so big :smile: CALL apoc.periodic.iterate() is the right choice :slight_smile: Good job!

1 Like

I am sorry to bother you guys again. I am trying to setup another relationship where I want to validate one of the properties of node label P:Products p3 first then match with I.p4 = P.p4 OR I.p5 = P.p5.. Here is the query I tried but it did create relationships by ignoring my p3 condition

call apoc.periodic.iterate("match (I:Inventory) (P:Products) where I.p3 <> '0' AND I.p4= P.p4 OR I.p5 = P.p5 return I,P","merge (I) -[:PRODUCES]->(P)",{batchSize:10000, parallel:false})

Am I missing something here ? Thanks in advance!

Yes it's because of the OR, so must specify your AND condition to both parts :slight_smile:

call apoc.periodic.iterate("
    MATCH (I:Inventory) (P:Products)
    WHERE I.p3 <> '0' AND I.p4 = P.p4
    OR I.p3 <> '0' AND I.p5 = P.p5
    RETURN I,P
    ","
    MERGE (I) -[:PRODUCES]->(P)
    ",{batchSize:10000, parallel:false})

And make sure your p3 property is a string and not an integer :slight_smile:

First of all Thanks! I am a bit confused with this modified query. Could you please elaborate?
Not all my I nodes have values for p4 and p5. Some have p4 while p5 is a null string and vice versa. In rare cases, I have both p4 and p5 values. But I don't need to create relationships using both of them. Just either one is sufficient.
Similarly, my P nodes also have null p4 and p5.
This is why I chose to go with OR. I was under the impression that OR would pick either p4 or p5 from both I and P. Looks like my understanding is incorrect. Do you think your query would satisfy my requirement? Thanks!

It's the same query, I just added I.p3 <> '0' to both part of the OR:

(I.p3 <> '0' AND I.p4 = P.p4) OR (I.p3 <> '0' AND I.p5 = P.p5)

I'm trying to solve your p3 issue:)

ah I see. I am testing this against my data. let me see what I get back with.. thanks!