简体   繁体   中英

How to Create a Chain of Nodes Depending on a Property in Cypher

I'm having the following dataset in neo4j, representing metadata from the messaging app slack:

MERGE(abc:channel{name:'abc'})
MERGE(fgh:channel{name:'fgh'})
MERGE(a:message {text:'a', ts:'123.4', channel:'abc'})<-[:contains]-(abc)
MERGE(b:message {text:'b', ts:'123.8', channel:'abc'})<-[:contains]-(abc)
MERGE(c:message {text:'c', ts:'125.4', channel:'abc'})<-[:contains]-(abc)
MERGE(d:message {text:'d', ts:'130.4', channel:'abc'})<-[:contains]-(abc)
MERGE(e:message {text:'e', ts:'150.4', channel:'abc'})<-[:contains]-(abc)

MERGE(f:message {text:'f', ts:'100.0', channel:'fgh'})<-[:contains]-(fgh)
MERGE(g:message {text:'g', ts:'123.4', channel:'fgh'})<-[:contains]-(fgh)
MERGE(h:message {text:'h', ts:'150.0', channel:'fgh'})<-[:contains]-(fgh)
MERGE(i:message {text:'i', ts:'180.0', channel:'fgh'})<-[:contains]-(fgh)
MERGE(j:message {text:'j', ts:'180.2', channel:'fgh'})<-[:contains]-(fgh)

I want to create chains of messages in the following format: (a)<-[:follows]-(b)<-[:follows]-(c)<-[:follows]-(d)<-[:follows]-(e) (f)<-[:follows]-(g)<-[:follows]-(h)<-[:follows]-(i)<-[:follows]-(j) , based on the time they were written ts

I got the following code:

MATCH(msg:message)<-[:contains]-(cs:channel)
UNWIND cs AS Channel
    WITH collect(msg.ts) AS  messagestimeline, COUNT(msg) AS nomsg, Channel
    ORDER BY messagestimeline 
    FOREACH (i IN RANGE (1, nomsg-1)|
        MERGE (previousmessage {ts:  messagestimeline[i-1], channel:  Channel.name })
        MERGE (nextmessage {ts: messagestimeline[i], channel: Channel.name })
        MERGE (nextmessage)-[rel:follows]->(previousmessage)
        SET rel.delta_t = toFloat(messagestimeline[i])-toFloat(messagestimeline[i-1])
    )

and get the result: (a)-[:follows]->(b)-[:follows]->(c)-[:follows]->(d)-[:follows]->(e) (i)-[:follows]->(j)-[:follows]->(f)-[:follows]->(g)-[:follows]->(h)

Interestingly, the result does not change when I add a DESC to the ORDER BY clause

Any help on what I am doing wrong would be greatly appreciated, I'm sitting in front of this since 2 days and can't figure it out.

The following code does the trick:

MATCH(cs:channel)
UNWIND cs AS Channel
    MATCH(msgs)<-[:contains]-(Channel)
    WITH Channel, msgs ORDER BY msgs.ts 
    WITH collect(msgs.ts) as msgtimeline, count(msgs) as nom, Channel
    FOREACH(i IN RANGE(1,nom-1)|
        MERGE(prvsmsg{ts:msgtimeline[i-1], channel:Channel.name})
        MERGE(nxtmsg{ts:msgtimeline[i], channel: Channel.name})
        MERGE(prvsmsg)<-[rel:follows]-(nxtmsg)
        set rel.delta_t = toFloat(nxtmsg.ts)-toFloat(prvsmsg.ts)
        )

The difference is that I used the ORDER BY clause on a property of a bunch of nodes and created the list for the FOREACH statement afterwards. Why this makes such a big difference remains a mystery for me though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM