cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to deal with properties that have arithmetic relationship in neo4j

Dear All:
I want to build the following model in neo4j:
person hasProperty: Weight , Height, BMI.
BMI =Weight/Height^2 # kg/m^2
person is classified in (Thin, NormalWeight, OverWeight):
if Person.BMI <18.5 then
Person is Thin
else if (Person.BMI >=-18.5) and (Person.BMI <=-25) then
Person is NormalWeight
else if Person.BMI >25 then
Person is OverWeight

How do I create and store the above model schema in Neo4j?
Then, suppose I have height and weight data for thousands of people and need to query a list of those who are overweight, How do I model and store data for classes and instances?
I want to emphasize in particular that I want to store the above classification rules in neo4J graph data, not in a cypher query statement, I don't know if this idea will work.
Thanks a lot for any help!

Joylix

1 REPLY 1

@joylix4112

To create an arithmetic operation you could use the Apoc Trigger procedures
togheter with apoc.do.case to listen every change of Weight and Height properties to create BMI as a property and classification (in this case I stored Thin, NormalWeight, OverWeight as a label, but you could change it as a property)

That is:

call apoc.trigger.add("bmiIndex", "UNWIND (apoc.trigger.propertiesByKey($assignedNodeProperties, 'Weight') + apoc.trigger.propertiesByKey($assignedNodeProperties, 'Height') + apoc.trigger.propertiesByKey($removedNodeProperties, 'Weight') + apoc.trigger.propertiesByKey($removedNodeProperties, 'Height'))  as prop  // handle for Weight and Height assignation / removal
WITH distinct prop.node as node
where node:Person
CALL apoc.do.case([node.Height is null or node.Weight is null, 'REMOVE node.BMI RETURN node'], 'SET node.BMI = toFloat(node.Weight) / (toFloat(node.Height) ^ 2) RETURN node', {node: node}) yield value with value.node as node // if Height or Weight not set, I put BMI as null

CALL apoc.do.case([node.BMI is null, 'REMOVE node:Thin:OverWeight:NormalWeight', node.BMI < 18.5, 'SET node:Thin', node.BMI > 25, 'SET node:OverWeight'], 'SET node:NormalWeight', {node: node}) // I remove label if BMI null or I set the classification label based on BMI
YIELD value return value
", {phase: 'afterAsync'})

Otherwise, if you want to create something that doesn't require apoc and cypher statement,
you should use the TransactionEventListener, used by apoc under the hood, to listen for every transaction and create BMI and weight classification.