Cooking is an integral part of every home life. Being able to quickly decide what to have for breakfast, lunch, and dinner, and with a click to find a recipe that complies with your current diet, is the dream of every family. If you want to develop an application that can make millions of people happy by saving them time for their close ones, you are in the right spot.
With Neo4j, you can quickly graph a use case, fill it with real-world objects, and enjoy the interconnectedness of your data.
Let me show you how easy it is to model a domain such as Food Recipes.
The first thing you have to do is to find a recipe that you like and write down its main parts. They will be your graph nodes: pancake, almond flour, coconut flour, eggs, baking powder, vanilla extract, avocado oil, sea salt, recipe, nutrition facts, instructions.
Then, try to identify how these parts interact with each other. For example, pancake contains almond flour; recipe has nutrition facts; recipe is about pancakes; recipe starts with instruction; instruction 1 is followed by instruction 2; the last instruction results in food, etc. Continue until it feels complete.
Tip: The more connected your model is, the more possibilities you have to traverse it.
When you finish defining your graph nodes, assign labels to them. For example, you know that pancakes are food, but they are also used to make a cake. So, you add two labels next to pancake: Food and Ingredient. Then, you connect the pancake to its ingredients by adding the relationship contains. You can further model the link by assigning the property quantity:' '
to it, which can also be related to the node recipe. Then, you specify the nodes that have labels Food and Ingredient by adding the property name:' '
to them.
Continue like this to add properties to every node of your graph.
Note: For the example purposes, I have not added all domain connections and nodes because the graph would have become hardly readable.
Now, you can use Arrow Tool to create the graph model of your recipe by adding the nodes and relationships from Step 1 and 2. The Export Cypher option creates a query that you can use to import the graph in the Neo4j database.
CREATE
(`1` :Ingredient :Food {name:'Almond Flour'}) ,
(`2` :Ingredient :Food {name:'Coconut Flour'}) ,
(`3` :Ingredient :Food {name:'Almond milk'}) ,
(`4` :Ingredient :Food {name:'egg'}) ,
(`5` :Ingredient :Food {name:'baking powder'}) ,
(`6` :Ingredient :Food {name:'vanilla extract'}) ,
(`7` :Ingredient {name:'avocado oil'}) ,
(`8` :Ingredient :Food {name:'sea salt'}) ,
(`9` :Instruction {name:'Whisk all ingredients together in a bowl until smooth.',sequence:'1'}) ,
(`10` :Instruction {name:'Preheat an oiled pan on the stove over medium-low to medium heat.',sequence:'2'}) ,
(`11` :Instruction {name:'Drop the batter onto the hot pan and form into circles.',sequence:'3'}) ,
(`12` :Instruction {name:'Cover and cook until bubbles start to form.',sequence:'4'}) ,
(`13` :Instruction {name:'Flip and cook another until browned on the other side.',sequence:'5'}) ,
(`14` :Recipe {name:'Pancakes',suitable_for:'HFLC',course:'breakfast',calories:'268 kcal',prep_time:'5 min',cook_time:'15 min',servings:'6'}) ,
(`15` :Nutrition_Facts {serving_size:'Amount per serving',calories:'268 kcal',fat:'23 g',protein:'9 g',`total carbs`:'6 g'}) ,
(`16` :Ingredient :Food {name:'pancake'}) ,
(`1`)-[:`listed_in` ]->(`14`) ,
(`2`)-[:`listed_in` ]->(`14`) ,
(`3`)-[:`listed_in` ]->(`14`) ,
(`4`)-[:`listed_in` ]->(`14`) ,
(`5`)-[:`listed_in` ]->(`14`) ,
(`6`)-[:`listed_in` ]->(`14`) ,
(`7`)-[:`listed_in` ]->(`14`) ,
(`8`)-[:`listed_in` ]->(`14`) ,
(`14`)-[:`starts_with` ]->(`9`) ,
(`9`)-[:`next_instruction` ]->(`10`) ,
(`10`)-[:`next_instruction` ]->(`11`) ,
(`11`)-[:`next_instruction` ]->(`12`) ,
(`12`)-[:`next_instruction` ]->(`13`) ,
(`13`)-[:`results_in` ]->(`16`),
(`13`)-[:`next_instruction` ]->(`11`),
(`14`)-[:`has_nutrition_facts` ]->(`15`),
(`16`)-[:`has_nutrition_facts` ]->(`15`),
(`16`)-[:`contains` {quantity:'1 cup'} ]->(`1`) ,
(`16`)-[:`contains` {quantity:'1/4 cup'} ]->(`2`) ,
(`16`)-[:`contains` {quantity:'1/3 cup'} ]->(`3`) ,
(`16`)-[:`contains` {quantity:'3'} ]->(`4`) ,
(`16`)-[:`contains` {quantity:'1 tsp'} ]->(`5`) ,
(`16`)-[:`contains` {quantity:'1 tsp'} ]->(`6`) ,
(`16`)-[:`contains` {quantity:'1/4 cup'} ]->(`7`) ,
(`16`)-[:`contains` {quantity:'1/4 tsp'} ]->(`8`) ,
(`14`)-[:`is_about` ]->(`16`) ,
(`16`)-[:`is_prepared_through` ]->(`14`)
You can visualise your graph by using the following query.
MATCH p = (n)-->() RETURN p
If your model needs improving, follow the example in Step 3 and modify the code in a text editor. Visualise again. Repeat.
You can use Cypher queries to retrieve knowledge from your data.
You: Neo4j, show me the Nutrition Facts of the "Pancakes" recipe
MATCH (:Recipe {name: 'Pancakes'})-[:has_nutrition_facts]->(n:Nutrition_Facts)
RETURN n.`serving_size`,n.`calories`,n.`fat`,n.`protein`,n.`total carbs`
Neo4j:
You: Neo4j, give me the ingredients of a pancake
MATCH (food:Food)-[:contains]->(Ingredient)
RETURN food.name AS Food, collect(Ingredient.name) AS Ingredients
Neo4j:
You: Neo4j, give me the quantity of each ingredient
Query
MATCH (food:Food)-[c:contains]-> (i:Ingredient)
RETURN i.name AS Ingredient,c.quantity AS Quantity
ORDER BY c.quantity
Neo4j:
You: Neo4j, tell me how to prepare "Pancakes"
MATCH (r:Recipe)-[:starts_with]->(i:Instruction)-[:next_instruction*]->(i1)
RETURN r,i,i1
Neo4j:
You just saw how easy it is to start graphing and exploring a new domain with Neo4j. Continue by adding more recipes and ingredients or use this as a reference to model your case. Enjoy!