UNWIND [{name:'foo'},{name:'bar'}] as lorem
UNWIND [{name:'soo'},{name:'sar'}] as sorem
MERGE (s:Sorem) - [:LOREMED] -> (l:Lorem {
name: lorem.name
})
MERGE (s2:Sorem) - [:LOREMED] -> (l2:Lorem {
name: sorem.name
})
RETURN l
It correctly creates the data and there is no repeat in the graph but when I see the result it appears in repeating number. While RETURN l should only return:
You did 2 UNWINDs of 2 elements each, so you have 2 * 2 = 4 rows. Each element of your lorem appears twice for that total of 4 (foo with soo, foo with sar, bar with soo, bar with sar).
Looking JUST at that first MERGE, let's look at what happens:
MERGE the pattern for foo | soo. The pattern doesn't exist so it's created. A new :Sorem node is created without properties, a new :Lorem node is created with name = 'foo'. A :LOREMED relationship is created between them.
MERGE the pattern for foo | sar. The pattern exists (we created it in the previous step: a :Sorem node connected by a :LOREMED rel to a :Lorem node with the name 'foo'). No new nodes or rels are created.
MERGE the pattern for bar | soo. The pattern doesn't exist so it's created. A new :Sorem node is created without properties, a new :Lorem node is created with name = 'bar'. A :LOREMED relationship is created between them.
MERGE the pattern for foo | sar. The pattern exists (we created it in the previous step: a :Sorem node connected by a :LOREMED rel to a :Lorem node with the name 'bar'). No new nodes or rels are created.
We can ignore the second MERGE statement for now.
When we return l, cardinality is still 4 rows, nothing has been done to grow it (UNWIND, MATCH, OPTIONAL MATCH, CALL ... YIELD) or shrink it (LIMIT, aggregations, filtering from WHERE or MATCHes).
Your return will return 4 rows, but there are two l nodes, each one just gets repeated once.
If you wanted only two rows corresponding to the to l nodes, use RETURN DISTINCT l.
Yes, because you're looking at distinct combinations. DISTINCT applies to the entire row, not just a single element, so your distinct rows are the nodes corresponding with foo | soo, foo | sar, bar | soo, bar | sar. They are distinct.
You don't have all the nodes under the same variable, so if this is REALLY what you want you'll need to do some work in Cypher to gather them there, that way they'll all be under a single column.
Looking at your query, however, given that you're treating lorem elements and sorem elements exactly the same (creating the exact same pattern, and associating their names with a :Lorem element in all cases), it would actually be better to get them into the same column variable early on and treat them as the same, and that way we avoid the cross product you stumbled into, and you'll get expected results at the end.
Try this instead:
UNWIND [{name:'foo'},{name:'bar'}] + [{name:'soo'},{name:'sar'}] as lorem
MERGE (s:Sorem) - [:LOREMED] -> (l:Lorem {
name: lorem.name
})
RETURN l
In the query you posted, there is no need to UNWIND both (this creates a cross product) since you're doing the exact same thing for both variables, so it makes sense to keep them as one variable and treat them all the same. I can't provide good advice if the sample query isn't a good representation of the actual query.
Also, please read the linked knowledge base article on cardinality I provided earlier, it may help you understand how Cypher works here.
I think you still need to provide a better query. I would address that change by making a small tweak to how we set the property, to use name or other depending on what's available:
UNWIND [{name:'foo'},{name:'bar'}] + [{other:'soo'},{other:'sar'}] as lorem
MERGE (s:Sorem) - [:LOREMED] -> (l:Lorem {
name: coalesce(lorem.name, lorem.other)
})
RETURN l
I can keep solving these simple queries for you, but it won't make much difference if these don't resemble your actual queries.
Not quite sure I understand. The query I provided earlier uses coalesce(lorem.name, lorem.other), which means it will use the first term that is not null, so in the cases where the lorem has an other property but not a name property, it will use the other property as it's the first non-null value.
If that isn't what you need, you may need to explain what you need a bit more. CASE can be useful in these situations, but not currently with how you're using UNWIND. I'd need more details about what you're trying to do.
Maybe? If we assume the same inputs of [{name:'foo'},{name:'bar'}] as $var1 and [{other:'soo'},{other:'sar'}] as $var2, then we can use coalesce() again to set the name accordingly, and use the fact that name properties only exist in $var1 for use in our CASE:
UNWIND $var1 + $var2 as lorem
MERGE (s:Sorem) - [:LOREMED] -> (l:Lorem {
name: coalesce(lorem.name, lorem.other),
mm: CASE WHEN exists(lorem.name) THEN 'ok' ELSE 'good' END
})
Though it may be more useful to instead use a list membership check for lorem in $var1, that would cope better if properties can be all the same between $var1 and $var2.
UNWIND $var1 + $var2 as lorem
MERGE (s:Sorem) - [:LOREMED] -> (l:Lorem {
name: coalesce(lorem.name, lorem.other),
mm: CASE WHEN lorem IN $var1 THEN 'ok' ELSE 'good' END
})