deus
deus

Reputation: 77

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 ?

Upvotes: 4

Views: 1047

Answers (2)

albertoperdomo
albertoperdomo

Reputation: 1949

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

Upvotes: 7

Stefan Armbruster
Stefan Armbruster

Reputation: 39925

I guess you frequently need to calculate the sum of all purchases bewteen a specfic agent A and product P. If so it might be beneficial to introduce a a total_purchases relationship between A and P holding the sum. Whenever you add a new purchase, make sure to update the existing total_purchases relationship.

Another thing to consider is if the current approach of having purchases relationships hides some domain concepts. I can think of agents placing multiple orders. Each order contains multiple items - which is what you currently refer using the purchases relationship. So the order would be a node holding e.g. date connected to 1) the agent and 2) to the products.

In general everything being a concept on its own or having an identity should be modelled as a node.

Upvotes: 4

Related Questions