2
votes

I am attempting to combine any nodes returned by one of three match conditions:

(p)-[:HAS_CAL]->(prodCal:ProdCal)-[:DELIVERS_TO]->(:Country {name: "USA"})
(p)-[:HAS_CAL]->(prodCal:ProdCal)-[:DELIVERS_TO]->(z:ZipCode {zipCode: delivZip})
(p)-[:HAS_CAL]->(prodCal:ProdCal)-[:DELIVERS_TO]->(zr:ZipRange) where zr.fromZip >= delivZip or zr.thruZip <= delivZip

With any results that come back from any of those match conditions I'd like to then perform another match. I'm guessing that means using either a foreach or unwind, in a fashion such as this:

unwind prodCals as prodCal
match (prodCal)-[dd:DELIVERS]->(delivDay:Day) where dd.cutoff > (timestamp() / 1000)
return delivDay

I've tried several things but cannot get this to work. The end result should be a set of delivDays that are returned by each of the match (prodCal)-[dd:DELIVERS]->(delivDay:Day) ... statements.

Update:

I seem to have a solution that works:

...
with p, delivZip
optional match (p)-[:HAS_CAL]->(prodCal1:ProdCal)-[:DELIVERS_TO]->(z:ZipCode {zipCode: delivZip})
with p, delivZip, prodCal1
optional match (p)-[:HAS_CAL]->(prodCal2:ProdCal)-[:DELIVERS_TO]->(zr:ZipRange) where zr.fromZip >= delivZip or zr.thruZip <= delivZip
with p, collect(prodCal1) + collect(prodCal2) as prodCals
optional match(p)-[:HAS_CAL]->(prodCal3:ProdCal)-[:DELIVERS_TO]->(:Country {name: "USA"})
with collect(prodCal3) + prodCals as prodCals2
unwind prodCals2 as cal
match (cal)-[dd:DELIVERS]->(delivDay:Day) where dd.cutoff > (timestamp() / 1000)
return delivDay

I'd love to know if there is a more elegant solution though.

1

1 Answers

2
votes
WITH p, delivZip
MATCH (p) - [:HAS_CAL] -> (prodCal:ProdCal)
WHERE (prodCal) - [:DELIVERS_TO] -> (:Country {name: "USA"})
OR (prodCal) -[:DELIVERS_TO] -> (:ZipCode {zipCode: delivZip})
OR ANY( path IN (prodCal) - [:DELIVERS_TO] -> (:ZipRange) WHERE delivZip >= LAST(NODES(path))['fromZip'] AND delivZip <= LAST(NODES(path))['thruZip'] )
WITH prodCal
MATCH (prodCal)-[dd:DELIVERS]->(delivDay:Day) WHERE dd.cutoff > (TIMESTAMP() / 1000)
RETURN delivDay

Elegance is a subjective property, of course, but this avoids having to worry about COLLECT/UNWIND shenanigans, you'll avoid errors from accidental NULL results from OPTIONAL MATCH, and it'll be incidentally more performant. If you have the option to refactor, I would replace those :ZipRange nodes with relationships to individual :ZipCode nodes; even if you have to make 100000 relationships, that's well within capacity, and will simplify all your queries.