Search code examples
neo4jcypherneo4j-apoccypher-3.1

Neo4j/Cypher: Passing properties through WITH


I am posting a new question because this is a separate but related issue to this question: Neo4j: Link Different Nodes to the one node

The below query is returning the correct number of nodes.

MATCH (act)--(obj) 
WHERE obj.filename IN ["6013", "6005"]
WITH act.timestamp as timestamp, collect(DISTINCT act) as acts
CREATE (a:Abs{name: 'SigEvent'}) 
FOREACH (act in acts | CREATE (act)-[:LINK]->(a))

The following query is ignoring the COLLECT and creating an a node for every entry in the collection instead of creating an a node for every pair. Also, when I move the CREATE outside of the FOREACH I get the following error: Type mismatch: expected Any, Map, Node or Relationship but was List<Map>.

 MATCH (act)--(obj) 
    WHERE obj.filename IN ["6013", "6005"]
    WITH act.timestamp as timestamp, collect({act:act, obj:obj}) as pairs
    CREATE (a:act{ Event: pairs.obj.filename, Description:pairs.act.message, timestamp:timestamp}) 
         FOREACH (pair in pairs | CREATE (pair)-[:LINK]->(a))

Example Data set:

Set 1: (act: "Event Log", timestamp: 3461000) (act: "Uptime Report", timestamp: 3461000)

Set 2: (act: "Event Log", timestamp: 149100) (act: "Uptime Report", timestamp: 149100)

Desired result:

(a {Source: "Event Log" & "UPtime Report", timestamp: 3461000})<-[:LINk]-(act)

(a {Source: "Event Log" & "UPtime Report", timestamp: 149100)<-[:LINk]-(act)


Solution

  • When you use COLLECT (or any aggrogate) all the other non-aggrogates in the WITH/RETURN will be used as the GROUP BY keys. So by adding act and obj, COLLECT is collecting all act with the same timestamp, act, and obj (aka, 1 act per act). If you need to aggregate multiple columns, you can aggregate multiple columns/properties at the same time

    MATCH (act)--(obj) 
    WHERE obj.filename IN ["6013", "6005"]
    WITH act.timestamp as timestamp, COLLECT(DISTINCT act.message) as messages, COLLECT(DISTINCT obt.filename) as filenames, COLLECT(act) as acts
    CREATE (a{ Event: filenames, Description:messages, timestamp:timestamp})
    FOREACH (act in acts | CREATE (act)-[:LINK]->(a))