How to iterate a cypher query multiple time

Hi Team,

I have a cypher query which is basically an algorithm which i need to iterate multiple times in order to get the final result. It's same like how we set iteration options in GDS libraries.

I have tried using foreach with range and it throws an error " Invalid use of match inside foreach". What could be the possible ways to add for loop like functionality in graph?

Hello @spsingh559 :slight_smile:

Can you show us some code? :slight_smile:

Regards,
Cobra

sure, here is one algorithm we have created for risk propagation among Person node based on their interaction with each other.

with 0.8 as Decay, 20 as itr

match (p:Person)-[r:MET_EVENT]->(a:Person) where r.timeEnd>Datetime()-Duration('P14D')
with toFloat(SUM(a.riskScore))/toFloat(count(a)) * Decay as score,p

FOREACH ( ignoreMe in CASE WHEN p.riskScore<score THEN [1] ELSE END | set p.riskScore=score )
return SUM(p.riskScore) as totalRiskScore

Note : this query i need to run more than 20 + time till there is convergence . My aim is to iterate the query till totalRiskScore is converged to a point, when there is no further change in score. That can be achieved by iterating this query over 20 - 25 times. Now how i would iterate this query multiple times.

Did you to use UNWIND for your iteration? :slight_smile:

Regards,
Cobra

yes, i have tried with unwind too, but in case of unwind, query is iterative over a given range, but value of result is not getting changes.

See the code snippet with unwind -

UNWIND range(0,10) as iterations
with 0.8 as Decay, 20 as itr, iterations

match (p:Person)-[r:MET_EVENT]->(a:Person) where r.timeEnd>Datetime()-Duration('P14D')
with toFloat(SUM(a.riskScore))/toFloat(count(a)) * Decay as score,p, iterations

FOREACH ( ignoreMe in CASE WHEN p.riskScore<score THEN [1] ELSE END | set p.riskScore=score )
return SUM(p.riskScore) as totalRiskScore,iterations

Result :

Now you can notice that risk score is remain same for each iteration, but ideal behaviour is risk score will keep on changing over each iteration .

Yeah, you right :slight_smile:

Maybe UNWIND + your cypher request in apoc.cypher.run() doc

Regards,
Cobra

finally i found the way using your shared document. I am using apoc.cypher.doIt -> as i am modifying records also. Run is for only reading the records.

Upadted snippet is

UNWIND range(0,100) as iterations

call apoc.cypher.doIt("
with 0.8 as Decay, 20 as itr
match (p:Person)-[r:MET_EVENT]->(a:Person) where r.timeEnd>Datetime()-Duration('P14D')
with toFloat(SUM(a.riskScore))/toFloat(count(a)) * Decay as score,p

FOREACH ( ignoreMe in CASE WHEN p.riskScore<score THEN [1] ELSE END | set p.riskScore=score )
return SUM(p.riskScore) as totalRiskScore
",{}) yield value

return value

Now value is changing over each iteration

1 Like

Nice, I'm happy to hear it, good job :slight_smile: