The purpose of this food recommendation system is to isolate peoples' certain heath problems and preferences and give recommendations to recipes that satisfy their needs. This model organizes a collection of food recipes and combines it with a social network of people. This way, people can cook for their friends based on things that they both love and that will not be detrimental to their health.
There are three types of nodes that are taken into consideration:
Each person node represents a single person from a group of friends, each with unique attributes. In total, there are 6 people within the group of friends.
-
Person
-
Recipe
-
Product
The recipe nodes represent recipes for different foods and dishes. The attributes of it taken into consideration are: the name of the recipe; the formula; and the type of meal it is designed for, such as whether it is a dessert or a main dish. There are 5 total recipes.
The product nodes represent the ingredients found within the recipes or within the allergies that each person had. There are 16 total products.
There are many types of relationships and the attributes for each type.
IS_FRIEND_OF
relationship is used to describe if a person is friends with another person.
-
ex. Bob IS_FRIEND_OF Alice
IS_ALLERGIC_TO
describes if one person is allergic to a specific product or ingredient.
-
ex. Bob IS_ALLERGIC_TO potato
LOVES
is used to describe if a person loves a specific product.
-
ex. Bob LOVES pasta
HATES
is used to describe if a person hates a specific product.
-
ex. Bob HATES rice
HAS_INGREDIENT
is used to form a relationship between the recipe and the product.
-
ex. potatoes HAS_INGREDIENT potato
The three different nodes used in this Food Recipes Recommendation Graph can be linked in the five different ways described in the relationship section.
-
Person uses the
Is_FRIEND_OF
relationship to connect to another Person -
Person uses the
IS_ALLERGIC_TO
relationship to connect to a specific Product -
Person uses the
LOVES
relationship to connect to a specific Product -
Person uses the
HATES
relationship to connect to a specific Prodcut -
Recipe uses the
HAS_INGREDIENT
relationship to connect it to a Product
The table below summarizes the data for each person that we have added to the database.
Person | Is Friend Of | Is Allergic To | Loves | Hates |
---|---|---|---|---|
Michael |
Cathy |
cow milk |
chocolate |
bananas |
Mateo |
gluten |
|||
wheat |
||||
Cathy |
Michael |
nuts |
chocolate |
|
wheat |
||||
Mateo |
Michael |
strawberries |
apples |
|
Peter |
John |
gluten |
||
Mary |
||||
John |
Peter |
gluten |
||
Mary |
Peter |
cow milk |
||
apples |
This table organizes the Recipes and which ingredients they use.
Recipe | Type | Ingredients |
---|---|---|
chocolate soup |
dessert |
passion fruit, coconut milk, chocolate, sugar |
chocolate cake |
dessert |
chocolate, wheat, sugar, eggs |
strawberry ice cream |
dessert |
water, surgar, strawberries |
tomato soup |
starter |
tomatoes, water, rice |
tomato sauce |
sauce |
tomatoes, water, onion |
The application can be used to identify and answer specific questions pertaining to the different peopele and their food allergies. Below are examples of queries that can be used to find reccomendations:
MATCH (m:Person { name:"Peter" })-[IS_FRIEND_TO]-(f:Person)
RETURN f
This query would be useful if you were just getting an idea of who is friends with who. If you are having a dinner party and invited Peter, you could see who he may bring to the party as well. Using this information, you could create a query that found a recipe that they would all enjoy.
MATCH(n:Recipe{type:"dessert"})
Return n
If your database had a lot of recipes, you could choose to just look at the desserts. This query would filter out all of the recipes and give you back just ones with the type "dessert".
MATCH(n:Recipe{name:"Chocolate soup"})-[:HAS_INGREDIENT]->(r:Product)
Return r
MATCH(n:Recipe{name:"Chocolate cake"})-[:HAS_INGREDIENT]->(r:Product)
Return r
MATCH(n:Recipe{name:"Tomato soup"})-[:HAS_INGREDIENT]->(r:Product)
Return r
MATCH(n:Recipe{name:"Strawberry icecream"})-[:HAS_INGREDIENT]->(r:Product)
Return r
MATCH(n:Recipe{name:"Tomato sauce"})-[:HAS_INGREDIENT]->(r:Product)
Return r
This query is useful in looking at all the ingredients that are used to make a specific recipe. You would use this information if you were going to buy the ingredients.
MATCH(n:Person)-[:IS_ALLERGIC_TO]->(r:Product)
Return n,r
You could use this query to get an overall picture of what people are allergic to. By looking at this query you can see that Cathy is allergic to nuts, Cathy and Michael are allergic to wheat, Michael and Mary are allergic to cow milk, Mary is allergic to apple, and Michael, Peter, and John are allergic to gluten. This could be useful if you want to see an ingredient tht the most people are allergic to before making a recipe.
MATCH (m:Person { name:"Cathy" })-[:LOVES]->(good_food:Product)
WITH m, good_food
RETURN good_food
This query returns one ingredient that Cathy loves, which is chocolate. Maybe if you are making a recipe for Cathy using this data, you would make chocolate soup or chocolate cake since it contains an ingredient that she loves.
//check what ingredients Cathy loves
MATCH (m:Person { name:"Cathy" })-[:LOVES]->(good_food:Product)
WITH m, good_food
//checking what Cathy should not eat
MATCH (m:Person { name:"Cathy" })-[:IS_ALLERGIC_TO|HATES]->(bad_food:Product)
WITH m, bad_food
//checking the recipes that Cathy should not eat
MATCH (r:Recipe)-[:HAS_INGREDIENT]->(p:Product)
WITH m, bad_food, p, r
WHERE p = bad_food
WITH m, bad_food, r AS bad_recipe
//checking the recipes that Cathy can eat
MATCH (r:Recipe)-[:HAS_INGREDIENT]->(p:Product)
WITH m, bad_recipe, r
WHERE NOT (r = bad_recipe)
WITH r AS rec_recipe, m
//return recipe that she can eat that includes ingredient she loves
MATCH (m)-[:LOVES]->(favorite:Product)<-[HAS_INGREDIENT]-(rec_recipe)
RETURN DISTINCT rec_recipe.name as recommended_recipe
This query takes into consideration Cathy’s ingredient that she loves. First it checks what ingredient Cathy loves, then it checks what ingredients she is allergic to or hates, then it eliminates the recipes that contain these bad ingredients. Finally, it returns a recipe that includes the ingredient she loves and is safe for her to eat based on her wants and needs.
MATCH ()-[:IS_ALLERGIC_TO]->(r:Product)
WITH COUNT(*) AS total
MATCH ()-[a:IS_ALLERGIC_TO]->(r:Product)
WITH total, r.name AS name, count(a) AS each_sum
RETURN name,(each_sum*100.0)/(total)*1.0 AS percentage
ORDER BY percentage ASC , name
MATCH ()-[:IS_ALLERGIC_TO]->(r:Product)
WITH COUNT(*) AS total
MATCH ()-[a:IS_ALLERGIC_TO]->(r:Product)
WITH total, r.name AS name, count(a) AS each_sum
RETURN name,(each_sum*100.0)/(total)*1.0 AS percentage
ORDER BY percentage DESC , name
Finding the least and most commmon food allergies would be especially useful if throwing a party. If you were to invite a lot of people, you could see what ingredient most people are allergic to so that you can avoid that in all your dishes, if possible.
MATCH (r:Recipe{type:"dessert"})-[i:HAS_INGREDIENT]->(p:Product)
WITH p.name as name, count(i) as sum
RETURN name
ORDER BY sum desc
You could look at the products that are most often used in desserts if you aren’t sure what you want to make. If you saw that cow milk was a common ingredient and you didn’t have very much, then you would maybe decide to make something else.
//checking what Michael should not eat
MATCH (m:Person { name:"Michael" })-[:IS_ALLERGIC_TO|HATES]->(bad_food:Product)
WITH m, bad_food
//checking the recipes for desserts that Michael should not eat
MATCH (r:Recipe { type:"dessert" })-[:HAS_INGREDIENT]->(p:Product)
WITH m, bad_food, p, r
WHERE p = bad_food
WITH m, bad_food, r AS bad_recipe
//checking the recipes for dessert that Michael can eat
MATCH (r:Recipe { type:"dessert" })-[:HAS_INGREDIENT]->(p:Product)
WITH m, bad_recipe, r
WHERE NOT (r = bad_recipe)
WITH r AS rec_dessert, m
//checking the favourite ingredients that the allowed recipe can contain
MATCH (m)-[:LOVES]->(favorite:Product)<-[HAS_INGREDIENT]-(rec_dessert)
RETURN DISTINCT rec_dessert.name as recommended_dessert
If Michael wanted a dessert, the program would check what Michael is allergic to or hates, and then check the recipes that include these ingredients. It would then eliminate the recipes that included the "bad food" and find recipes of the desserr type that had an ingredient that he loves and is not allergic to. This query would ensure that the dessert recommended was safe for him to eat and that he would enjoy it.
I (Michael) feel like cooking something of tomatoes and rice, what can I cook with these products (taking into account my preferences)?
//checking products Michael should not eat
MATCH (m:Person { name:"Michael" })-[:IS_ALLERGIC_TO|HATES]->(bad_food:Product)
WITH bad_food
//checking the recipes that Michael should not eat
MATCH (r:Recipe)-[:HAS_INGREDIENT]->(p:Product)
WITH bad_food, p, r
WHERE p = bad_food
WITH bad_food, r AS bad_recipe
//checking if 2 ingredients match somewhere and Michael can eat this food
MATCH (tomato:Product{ name:"tomato" })<-[:HAS_INGREDIENT]-(r:Recipe)-[:HAS_INGREDIENT]->(rice:Product{ name:"rice" })
WITH r, bad_food, bad_recipe
WHERE NOT (r = bad_recipe)
MATCH (r)-[:HAS_INGREDIENT]->(p:Product)
WITH r.name as recipe, p
return recipe, collect(p.name) as ingredients
In this scenario, Michael wants to focus on the products of tomatoes and rice. First it would look at what he is allergic to and hates and then eliminate the recipes that contain these ingredients. Then, it would match the tomato and rice ingredients to a recipe that was safe for him and that he liked that also contained tomatoes and rice.
//cheching products Michael and his friends should not eat
MATCH (my_bad_food:Product)<-[:IS_ALLERGIC_TO|HATES]-(m:Person { name:"Michael" })-[IS_FRIEND_TO]-(f:Person)-[:IS_ALLERGIC_TO|HATES]->(bad_food:Product)
WITH m, bad_food, my_bad_food
//checking the recipes for desserts that they should not eat
MATCH (r:Recipe { type:"dessert" })-[:HAS_INGREDIENT]->(p:Product)
WITH m, bad_food, my_bad_food, p, r
WHERE p = bad_food OR p = my_bad_food
WITH m, r AS bad_recipe
//checking the recipes for dessert that they can eat
MATCH (r:Recipe { type:"dessert" })-[:HAS_INGREDIENT]->(p:Product)
WITH m, bad_recipe, r
WHERE NOT (r = bad_recipe)
WITH r AS rec_dessert, m
//checking the favourite ingredients that the allowed recipe can contain
MATCH (m)-[:LOVES]->(favorite:Product)<-[:HAS_INGREDIENT]-(rec_dessert)
RETURN DISTINCT rec_dessert.name as recommended_dessert
This scenario would be the most realisitc to what I see the program being used for. If you want to find a dessert that satisfies all of your friends' wants and needs, you would first eliminate the recipes that contained ingredients that you nad your connection of friends hated and are allergic to. Then, you would narrow down the recipes to just the desserts and see which recipe contains the most favored ingredients. This recipe would be recommended for you to make because it takes into consideration all of your friends, their allergies, and their likes and dislikes.
This type of food recommendation system could be really useful on a recipe social network site. People could create a profile and input ingredients they are allergic to, things the love, and things they hate. The site can then narrow down personalized recipes that fit their needs. People could also link with their friends' profiles and search recipes that match both of their needs if they are going to cook something together. It could also be useful when preparing something for a friend, as you will be able to see their allergies and if they love or hate certain ingredients. I think this would be most useful if you coul dcreate "Events" and the website can find recipes that everyone will like and be able to eat.
//Person
CREATE (michael:Person{name:'Michael'}),
(cathy:Person{name:'Cathy'}),
(mateo:Person{name:'Mateo'}),
(peter:Person{name:'Peter'}),
(john:Person{name:'John'}),
(mary:Person{name:'Mary'})
//Product
CREATE (chocolate:Product{name:'chocolate'}),
(cow_milk:Product{name:'cow_milk'}),
(gluten:Product{name:'gluten'}),
(nuts:Product{name:'nuts'}),
(wheat:Product{name:'wheat'}),
(passion_fruit:Product{name:'passion fruit'}),
(coconut_milk:Product{name:'coconut milk'}),
(sugar:Product{name:'sugar'}),
(egg:Product{name:'egg'}),
(apple:Product{name:'apple'}),
(tomato:Product{name:'tomato'}),
(water:Product{name:'water'}),
(rice:Product{name:'rice'}),
(banana:Product{name:'banana'}),
(strawberry:Product{name:'strawberry'}),
(onion:Product{name:'onion'})
//Recipe
CREATE (chocolate_soup:Recipe{name:'Chocolate soup', type:'dessert', formula:'formula for the Chocolate soup'}),
(chocolate_cake:Recipe{name:'Chocolate cake', type:'dessert', formula:'formula for the Chocolate cake'}),
(tomato_soup:Recipe{name:'Tomato soup', type:'starter', formula:'formula for the Tomato soup'}),
(strawberry_icecream:Recipe{name:'Strawberry icecream', type:'dessert', formula:'formula for the Strawberry icecream'}),
(tomato_sauce:Recipe{name:'Tomato sauce', type:'sauce', formula:'formula for the Tomato sauce'})
//Friendship
CREATE michael-[:IS_FRIEND_OF]->cathy,
cathy-[:IS_FRIEND_OF]->michael,
michael-[:IS_FRIEND_OF]->mateo,
mateo-[:IS_FRIEND_OF]->michael,
peter-[:IS_FRIEND_OF]->john,
john-[:IS_FRIEND_OF]->peter,
peter-[:IS_FRIEND_OF]->mary,
mary-[:IS_FRIEND_OF]->peter
//Allergies and preferences
CREATE michael-[:IS_ALLERGIC_TO]->cow_milk,
michael-[:IS_ALLERGIC_TO]->gluten,
michael-[:IS_ALLERGIC_TO]->wheat,
michael-[:LOVES]->chocolate,
michael-[:HATES]->banana,
cathy-[:IS_ALLERGIC_TO]->nuts,
cathy-[:IS_ALLERGIC_TO]->wheat,
cathy-[:LOVES]->chocolate,
mateo-[:LOVES]->strawberries,
mateo-[:HATES]->apples,
peter-[:IS_ALLERGIC_TO]->gluten,
john-[:IS_ALLERGIC_TO]->gluten,
mary-[:IS_ALLERGIC_TO]->cow_milk,
mary-[:IS_ALLERGIC_TO]->apple
//Recipes made of Products
CREATE chocolate_soup-[:HAS_INGREDIENT]->passion_fruit,
chocolate_soup-[:HAS_INGREDIENT]->coconut_milk,
chocolate_soup-[:HAS_INGREDIENT]->chocolate,
chocolate_soup-[:HAS_INGREDIENT]->sugar,
chocolate_cake-[:HAS_INGREDIENT]->chocolate,
chocolate_cake-[:HAS_INGREDIENT]->wheat,
chocolate_cake-[:HAS_INGREDIENT]->sugar,
chocolate_cake-[:HAS_INGREDIENT]->egg,
strawberry_icecream-[:HAS_INGREDIENT]->water,
strawberry_icecream-[:HAS_INGREDIENT]->sugar,
strawberry_icecream-[:HAS_INGREDIENT]->strawberry,
tomato_soup-[:HAS_INGREDIENT]->tomato,
tomato_soup-[:HAS_INGREDIENT]->water,
tomato_soup-[:HAS_INGREDIENT]->rice,
tomato_sauce-[:HAS_INGREDIENT]->tomato,
tomato_sauce-[:HAS_INGREDIENT]->water,
tomato_sauce-[:HAS_INGREDIENT]->onion