Search code examples
graphrediscypherredisgraph

Architecture and querying in RedisGraph


I'm new to graphs, RedisGraph and Cypher and this took me a few hours without solving.

I have users paying other users. A payment can be deposited from a user. Some other user can eventually withdraw that deposit, but a deposit can also never be withdrawn.

I ended up with this:

(u:User)-[d:Deposit]->[t:Transaction]<-[w:Withdrawal]-(u:User)

Howerver at some point I need to find the transactions that have no Withdrawal.

My 2 questions:

  • what would be a better architecture?
  • even though you have a better logic, what is the way to retrieve nodes without the Withdrawal edge in the example?

Help will be very much appreciated! 🙇🏻‍♂️


Solution

  • what would be a better architecture?

    I believe you refer to what is called "graph modelling". Graph modelling in the basic form consists out of deriving entities and verbs out of sentences

    • entities -> candidate labels
    • verbs -> candidate relationship types

    A payment can be deposited from a user. Some other user can eventually withdraw that deposit,

    • entities: Payment/Deposit/Transaction (I assume you use this interchangeably) and User
    • verbs: deposit and withdraw

    So you did a good job nailing that.

    With regards to your second question. Given two transactions

    (u1:User {uid:1})-[:Deposit]->(t1:Transaction {tid:1})<-[:Withdrawal]-(u3:User {uid:3})
    (u2:User {uid:2})-[:Deposit]->(t2:Transaction {tid:2})
    
    redis:6379> GRAPH.QUERY g "MERGE (u1:User {uid:1})-[:Deposit]->(t1:Transaction {tid:1})<-[:Withdrawal]-(u3:User {uid:3}) MERGE (u2:User {uid:2})-[:Deposit]->(t2:Transaction {tid:2})"
    1) 1) "Labels added: 2"
       2) "Nodes created: 5"
       3) "Properties set: 5"
       4) "Relationships created: 3"
       5) "Cached execution: 0"
       6) "Query internal execution time: 1.920000 milliseconds"
    

    You can add a WHERE NOT clause at query time

    MATCH (u:User)-[d:Deposit]->(t:Transaction)
    WHERE NOT ((t)<-[:Withdrawal]-())
    RETURN u.uid
    

    Which should only return the user with uid 2

    redis:6379> GRAPH.QUERY g "MATCH (u:User)-[d:Deposit]->(t:Transaction) WHERE NOT ((t)<-[:Withdrawal]-()) RETURN u.uid"
    1) 1) "u.uid"
    2) 1) 1) (integer) 2
    3) 1) "Cached execution: 0"
       2) "Query internal execution time: 0.816100 milliseconds"