Search code examples
neo4jcypher

Cypher logic gates -> where all


I'm looking for help with the syntax to create logic gates. enter image description here

I want to identify in which sims, which gates are open.

  • gate a:
    • only requires event 1
    • open in sim 1,2,3
  • gate b:
    • requires event 1 & 2
    • open in sim 2 & 3
  • gate c:
    • requires event 1, 2,3
    • only open in sim 3

Data created using:

CREATE 
(a:Gate {name: 'gate a'}),
(b:Gate {name: 'gate b'}),
(c:Gate {name: 'gate c'}),
(x1:X {name: 'sim 1'}),(x2:X {name: 'sim 2'}), (x3:X {name: 'sim 3'}),
(e1:E {name: 'event 1'}),(e2:E {name: 'event 2'}), (e3:E {name: 'event 3'}),
(e1)-[:AND]->(a),
(e1)-[:AND]->(b),
(e2)-[:AND]->(b),
(e1)-[:AND]->(c),
(e2)-[:AND]->(c),
(e3)-[:AND]->(c),
(x1)-[:HAS]->(e1),
(x2)-[:HAS]->(e1),
(x2)-[:HAS]->(e2),
(x3)-[:HAS]->(e2),
(x3)-[:HAS]->(e1),
(x3)-[:HAS]->(e3)

Solution

  • Assuming that your DB has no duplicate HAS or AND relationships (between the same pair of nodes), you can:

    1. Count the number of Events for each Gate.
    2. Create a mapping from the internal ID of each Gate to its count.
    3. Count the number of Events for each sim/Gate pair.
    4. Keep only sim/Gate pairs that have an Event count equal to the count in the map for the same Gate.
    5. Return the remaining pairs.

    For example (this also sorts the results by sim.name):

    MATCH (e)-[:AND]->(g:Gate)
    WITH ELEMENTID(g) as gId, COUNT(e) AS gEventCount
    WITH apoc.map.fromPairs(COLLECT([gId, gEventCount])) AS gIdCountMap
    MATCH (sim:X)-[:HAS]->(event)-[:AND]->(gate)
    WITH sim, gate, gIdCountMap, COUNT(event) AS sgEventCount
    WHERE gIdCountMap[ELEMENTID(gate)] = sgEventCount
    RETURN sim, gate
    ORDER BY sim.name
    

    The result of above query is:

    ╒════════════════════╤════════════════════════╕
    │sim                 │gate                    │
    ╞════════════════════╪════════════════════════╡
    │(:X {name: "sim 1"})│(:Gate {name: "gate a"})│
    ├────────────────────┼────────────────────────┤
    │(:X {name: "sim 2"})│(:Gate {name: "gate a"})│
    ├────────────────────┼────────────────────────┤
    │(:X {name: "sim 2"})│(:Gate {name: "gate b"})│
    ├────────────────────┼────────────────────────┤
    │(:X {name: "sim 3"})│(:Gate {name: "gate a"})│
    ├────────────────────┼────────────────────────┤
    │(:X {name: "sim 3"})│(:Gate {name: "gate b"})│
    ├────────────────────┼────────────────────────┤
    │(:X {name: "sim 3"})│(:Gate {name: "gate c"})│
    └────────────────────┴────────────────────────┘