Search code examples
neo4jmodelinggraph-databases

Neo4j Database modeling for Multi Level Marketing


I'm trying to model a graph database for neo4j database. Here's the details:

Agents - Products - Ranks - Commissions.

There will be agents. There will be products ( say health products ).

An agent will join under another agent or can join directly. An agent can have only one parent but multiple children. There's no limit to the breadth and depth for joining agents under other agents.

Agents will be promoted and the rank depends on their total value of the products they purchased. Agents are given commission on monthly basis and that depends on their total value of the products they and their children purchased in a month.

Node : Agent { name, age, ..., rank } A1, A2, A3...

Node : Product { name, description, ..., price } P1, P2, P3...

Relationship : purchases { date, time, quantity, total pay }

( Agent ) -[:purchases]-> ( Product )

Agent can purchase multiple products at a time. Agent can purchase multiple times the same product.

example :

A1{ 'John Doe', '34', ..., '4' }

P1{ 'Px1', 'desx1', ..., '$2.3' }

A1 -[ :purchases { 03-01-2014, 09.30, 02, '$4.6' } ]-> ( P1 )

A1 -[ :purchases { 07-01-2014, 13.45, 01, '$2.3' } ]-> ( P1 )

? This is where I am stuck. So, here I need to create a relationship [:purchases] every time an agent buys a product even if it's the same product?

Will multiple relationship with the same type and label in between same two nodes in this scenario be efficient ? Because the agents will likely to purchase same products often frequently, this will create a bigger no. of multiple relationships between the same nodes.

Is this model follows a standard modelling principle ? Can anyone suggests a better modelling or correction ?


Solution

  • As Stefan suggested, I'd introduce Purchase nodes that have relationships with the products and also store the purchase value in that node. That way you can restrict the query to the purchases, without having to go deeper to reach the products.

    (:Agent)-[:made]->(:Purchase {date: XXX, value: XXX})-[:HAS]->(:Product)
    

    Let's say we have a relationship :WORKS_FOR to relate children agents to their parents:

    (a1:Agent)-[:WORKS_FOR]->(a2:Agent)
    

    This simple query will give you the sum of purchases every agent has done him/herself, without taking into account his children:

    MATCH (parent:Agent)-[:MADE]->(p:Purchase) RETURN parent.name, sum(p.value)
    

    Now, if you additionally want to take into account the purchases of the agents' children you can do:

    MATCH (parent:Agent)-[:MADE]->(p:Purchase) WITH parent, sum(p.value) AS own_value OPTIONAL MATCH (parent)<-[:WORKS_FOR*]-(child:Agent)-[:MADE]->(pc:Purchase) RETURN parent.name, own_value + sum(pc.value) as total_value