-
-
Save CalvinHarrisUK/10111353 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
= Retail Graph = | |
The significant functional differentiation of Neo4j in the retail space is the ability to quickly traverse interconnected datasets and make recommendations in “real time”. Competing approaches require large batch processing activities done offline to compute recommendations against large aggregate datasets, usually as nightly routines. Others attempt to parameterize or profile products and users, leaving the connection of interests and products simply to keyword matching and categorization. These methods produce results that can quickly become stale and outdated if they are not done frequently and lack flexibility and capabilities to dynamically change . | |
:neo4j-version: 2.0.1 | |
:author: Amanda | |
:twitter: @pandamonial | |
:tags: domain:Retail | |
//hide | |
//setup | |
[source,cypher] | |
---- | |
CREATE (froyo:Item{sku: "82635346282", description: "Low Fat Frozen Yogurt", rating: 10}) | |
CREATE (monster:Item{sku: "070847811169", description: "Monster Energy Drink", rating: 10}) | |
CREATE (mushedCarots:Item{sku: "251712725147", description: "baby carrots", rating: 8}) | |
CREATE (mushedPeas:Item{sku: "2929837251", description: "Organic Baby Mushed Peas", rating: 10}) | |
CREATE (pringles:Item{sku: "625112728275", description: "BBQ Pringle Potato Chips", rating: 6}) | |
CREATE (nuts:Item{sku: "2735272475", description: "Organic Healthy Nuts", rating: 9}) | |
CREATE (diapers:Item{sku: "98384251675", description: "Huggies Diapers", rating: 10}) | |
CREATE (celebMag:Item{sku: "627296345389", description: "Celebrity Weekly magazine", rating: 6}) | |
CREATE (oeggs:Item{sku: "79802372134", description: "Organic free range eggs", rating: 10}) | |
CREATE (eggs:Item{sku: "83736254673", description: "Big Farm Eggs", rating: 6}) | |
CREATE (ensure:Item{sku: "13242319687", description: "Ensure Health Drink", rating: 7}) | |
CREATE (sugarControlDrink:Item{sku: "19687324", description: "Diabetes Mgmt Drink", rating: 8}) | |
CREATE (milk:Item{sku: "231962387", description: "Milk", rating: 8}) | |
CREATE (oMilk:Item{sku: "239724863745", description: "Organic Milk", rating: 10}) | |
CREATE (vodka:Item{sku: "38634752937", description: "Grey Goose Vodka", rating: 10}) | |
CREATE (ooj:Item{sku: "5323232353", description: "Organic OJ with pulp", rating: 6}) | |
CREATE (oj:Item{sku: "624347537", description: "Minute Maid OJ", rating: 10}) | |
CREATE (Gin:Item{sku: "0938298337", description: "Hendricks Gin", rating: 10}) | |
CREATE (burgers:Item{sku: "234344536798", description: "Premade Burgers", rating: 10}) | |
CREATE (HCBeefNoodles:Item{sku: "72537704", description: "Healthy Choice Beef & Noodles", rating: 7}) | |
CREATE (fishsticks:Item{sku: "9862537282", description: "Premade fish sticks", rating: 4}) | |
CREATE (turkey:Item{sku: "73856654990", description: "Lean Ground Turkey", rating: 10}) | |
CREATE (motherhoodmag:Item{sku: "3635272134", description: "Motherhood Magazine", rating: 10}) | |
CREATE (baby:Category{name: "Baby"}) | |
CREATE (hb:Category{name: "Health and Beauty"}) | |
CREATE (frozen:Category{name: "Frozen"}) | |
CREATE (weightMgmt:Category{name: "Weight Management"}) | |
CREATE (premade:Category{name: "Pre-made meals"}) | |
CREATE (periodical:Category{name: "Periodical"}) | |
CREATE (organic:Category{name: "Organic"}) | |
CREATE (beverages:Category{name: "Beverages"}) | |
CREATE (meatsea:Category{name: "Meat and Seafood"}) | |
CREATE (breakfast:Category{name: "Breakfast and cereal"}) | |
CREATE (dairy:Category{name: "Dairy and eggs"}) | |
CREATE (alcohol:Category{name: "Alcohol"}) | |
CREATE (snacks:Category{name:"Snacks"}) | |
CREATE (motherhood:Interest{name: "Motherhood"}) | |
CREATE (diet:Interest{name: "Diet"}) | |
CREATE (reading:Interest{name: "Reading"}) | |
CREATE (fastmeals:Interest{name: "Fast meals"}) | |
CREATE (organicInterest:Interest{name: "Organic"}) | |
CREATE (celebrities:Interest{name: "Celebrity gossip"}) | |
CREATE (motherhood)-[:ALIGNS_TO]->(baby) | |
CREATE (fastmeals)-[:ALIGNS_TO]->(premade) | |
CREATE (diet)-[:ALIGNS_TO]->(weightMgmt) | |
CREATE (diet)-[:ALIGNS_TO]->(organic) | |
CREATE (organicInterest)-[:ALIGNS_TO]->(organic) | |
CREATE (reading)-[:ALIGNS_TO]->(periodical) | |
CREATE (motherhood)-[:ALIGNS_TO]->(periodical) | |
CREATE (motherhood)-[:ALIGNS_TO]->(premade) | |
CREATE (celebrities)-[:ALIGNS_TO]->(periodical) | |
CREATE (motherhoodmag)-[:ALIGNS_TO]->(motherhood) | |
CREATE (motherhoodmag)-[:ALIGNS_TO]->(periodicals) | |
CREATE (turkey)-[:ALIGNS_TO]->(meatsea) | |
CREATE (turkey)-[:ALIGNS_TO]->(organic) | |
CREATE (turkey)-[:ALIGNS_TO]->(weightmgmt) | |
CREATE (fishsticks)-[:ALIGNS_TO]->(meatsea) | |
CREATE (fishsticks)-[:ALIGNS_TO]->(frozen) | |
CREATE (fishsticks)-[:ALIGNS_TO]->(premade) | |
CREATE (burgers)-[:ALIGNS_TO]->(meatsea) | |
CREATE (HCBeefNoodles)-[:ALIGNS_TO]->(meatsea) | |
CREATE (burgers)-[:ALIGNS_TO]->(premade) | |
CREATE (burgers)-[:ALIGNS_TO]->(frozen) | |
CREATE (HCBeefNoodles)-[:ALIGNS_TO]->(premade) | |
CREATE (HCBeefNoodles)-[:ALIGNS_TO]->(frozen) | |
CREATE (ooj)-[:ALIGNS_TO]->(beverages) | |
CREATE (ooj)-[:ALIGNS_TO]->(organic) | |
CREATE (oj)-[:ALIGNS_TO]->(beverages) | |
CREATE (ooj)-[:ALIGNS_TO]->(breakfast) | |
CREATE (oj)-[:ALIGNS_TO]->(breakfast) | |
CREATE (gin)-[:ALIGNS_TO]->(beverages) | |
CREATE (gin)-[:ALIGNS_TO]->(alcohol) | |
CREATE (vodka)-[:ALIGNS_TO]->(beverages) | |
CREATE (vodka)-[:ALIGNS_TO]->(alcohol) | |
CREATE (milk)-[:ALIGNS_TO]->(dairy) | |
CREATE (omilk)-[:ALIGNS_TO]->(dairy) | |
CREATE (milk)-[:ALIGNS_TO]->(breakfast) | |
CREATE (omilk)-[:ALIGNS_TO]->(breakfast) | |
CREATE (milk)-[:ALIGNS_TO]->(beverages) | |
CREATE (omilk)-[:ALIGNS_TO]->(beverages) | |
CREATE (omilk)-[:ALIGNS_TO]->(organic) | |
CREATE (sugarControlDrink)-[:ALIGNS_TO]->(beverages) | |
CREATE (sugarControlDrink)-[:ALIGNS_TO]->(premade) | |
CREATE (sugarControlDrink)-[:ALIGNS_TO]->(weightMgmt) | |
CREATE (ensure)-[:ALIGNS_TO]->(beverages) | |
CREATE (ensure)-[:ALIGNS_TO]->(breakfast) | |
CREATE (ensure)-[:ALIGNS_TO]->(premade) | |
CREATE (ensure)-[:ALIGNS_TO]->(weightMgmt) | |
CREATE (eggs)-[:ALIGNS_TO]->(dairy) | |
CREATE (eggs)-[:ALIGNS_TO]->(breakfast) | |
CREATE (oeggs)-[:ALIGNS_TO]->(dairy) | |
CREATE (oeggs)-[:ALIGNS_TO]->(breakfast) | |
CREATE (oeggs)-[:ALIGNS_TO]->(organic) | |
CREATE (oeggs)-[:ALIGNS_TO]->(weightMgmt) | |
CREATE (celebMag)-[:ALIGNS_TO]->(periodical) | |
CREATE (froyo)-[:ALIGNS_TO]->(weightMgmt) | |
CREATE (froyo)-[:ALIGNS_TO]->(dairy) | |
CREATE (froyo)-[:ALIGNS_TO]->(frozen) | |
CREATE (monster)-[:ALIGNS_TO]->(weightMgmt) | |
CREATE (monster)-[:ALIGNS_TO]->(beverages) | |
CREATE (mushedCarots)-[:ALIGNS_TO]->(baby) | |
CREATE (mushedPeas)-[:ALIGNS_TO]->(baby) | |
CREATE (mushedPeas)-[:ALIGNS_TO]->(organic) | |
CREATE (pringles)-[:ALIGNS_TO]->(snacks) | |
CREATE (nuts)-[:ALIGNS_TO]->(snacks) | |
CREATE (nuts)-[:ALIGNS_TO]->(organic) | |
CREATE (diapers)-[:ALIGNS_TO]->(baby) | |
CREATE (john:Person{name: "John", FBID: "700056692"}) | |
CREATE (alex:Person{name: "Alex", FBID: "637289273"}) | |
CREATE (meg:Person{name: "Meg", FBID: "234233942"}) | |
CREATE (john)-[:HAS_INTEREST]->(diet) | |
CREATE (john)-[:HAS_INTEREST]->(fastmeals) | |
CREATE (alex)-[:HAS_INTEREST]->(fastmeals) | |
CREATE (alex)-[:HAS_INTEREST]->(fastmeals) | |
CREATE (meg)-[:HAS_INTEREST]->(reading) | |
CREATE (meg)-[:HAS_INTEREST]->(motherhood) | |
CREATE (alex)-[:HAS_INTEREST]->(celbrities) | |
CREATE (fbpost:Post{text: "Really need to diet, I am up 50 lbs since the baby", timestamp:timestamp()}) | |
CREATE (fbevent:Event{description: "Baby Shower for Meg", date:"05/20/2014",tags:"Newborn,Baby",host:"John"}) | |
CREATE (fbevent)-[:IS_FOR]->(meg) | |
CREATE (john)-[:FRIEND]->(alex) | |
CREATE (john)-[:FRIEND]->(meg) | |
CREATE (alex)-[:FRIEND]->(meg) | |
CREATE (order1:PurchaseOrder{timestamp: 1334343434}) | |
CREATE (order2:PurchaseOrder{timestamp: 1347427853}) | |
CREATE (order3:PurchaseOrder{timestamp: 1357362549}) | |
CREATE (order4:PurchaseOrder{timestamp: 1363735248}) | |
CREATE (order5:PurchaseOrder{timestamp: 1373625909}) | |
CREATE (order6:PurchaseOrder{timestamp: 1392826528}) | |
CREATE (order8:PurchaseOrder{timestamp: 1382736281}) | |
CREATE (john)-[:PURCHASED]->(order1) | |
CREATE (order1)-[:HAS_ITEM]->(turkey) | |
CREATE (order1)-[:HAS_ITEM]->(oeggs) | |
CREATE (order1)-[:HAS_ITEM]->(ooj) | |
CREATE (order1)-[:HAS_ITEM]->(vodka) | |
CREATE (order1)-[:HAS_ITEM]->(nuts) | |
CREATE (john)-[:PURCHASED]->(order2) | |
CREATE (order2)-[:HAS_ITEM]->(turkey) | |
CREATE (order2)-[:HAS_ITEM]->(oeggs) | |
CREATE (order2)-[:HAS_ITEM]->(gin) | |
CREATE (order2)-[:HAS_ITEM]->(froyo) | |
CREATE (order2)-[:HAS_ITEM]->(monster) | |
CREATE (order2)-[:HAS_ITEM{giftwrap:true}]->(monster) | |
CREATE (john)-[:PURCHASED]->(order3) | |
CREATE (order3)-[:HAS_ITEM]->(burgers) | |
CREATE (order3)-[:HAS_ITEM]->(celebrities) | |
CREATE (order3)-[:HAS_ITEM]->(ooj) | |
CREATE (order3)-[:HAS_ITEM]->(ensure) | |
CREATE (meg)-[:PURCHASED]->(order4) | |
CREATE (order4)-[:HAS_ITEM]->(motherhoodmag) | |
CREATE (order4)-[:HAS_ITEM]->(turkey) | |
CREATE (order4)-[:HAS_ITEM]->(fishsticks) | |
CREATE (order4)-[:HAS_ITEM]->(celebrities) | |
CREATE (order4)-[:HAS_ITEM]->(monster) | |
CREATE (alex)-[:PURCHASED]->(order5) | |
CREATE (order5)-[:HAS_ITEM]->(mushedCarots) | |
CREATE (order5)-[:HAS_ITEM]->(mushedPeas) | |
CREATE (order5)-[:HAS_ITEM]->(diapers) | |
CREATE (order5)-[:HAS_ITEM]->(celebrities) | |
CREATE (order5)-[:HAS_ITEM]->(monster) | |
CREATE (order5)-[:HAS_ITEM]->(vodka) | |
CREATE (order5)-[:HAS_ITEM]->(oj) | |
CREATE (alex)-[:PURCHASED]->(order6) | |
CREATE (order6)-[:HAS_ITEM]->(mushedCarots) | |
CREATE (order6)-[:HAS_ITEM]->(mushedPeas) | |
CREATE (order6)-[:HAS_ITEM]->(diapers) | |
CREATE (order6)-[:HAS_ITEM]->(celebrities) | |
CREATE (order6)-[:HAS_ITEM]->(fishsticks) | |
CREATE (order6)-[:HAS_ITEM]->(burgers) | |
CREATE (order6)-[:HAS_ITEM]->(vodka) | |
CREATE (order6)-[:HAS_ITEM]->(oj) | |
CREATE (alex)-[:PURCHASED]->(order8) | |
CREATE (order8)-[:HAS_ITEM]->(vodka) | |
CREATE (order8)-[:HAS_ITEM]->(oj) | |
CREATE (order8)-[:HAS_ITEM]->(mushedCarots) | |
CREATE (order8)-[:HAS_ITEM]->(mushedPeas) | |
CREATE (order8)-[:HAS_ITEM]->(diapers) | |
CREATE (john)-[:POSTED]->(fbpost) | |
CREATE (alex)-[:LIKED]->(fbpost) | |
CREATE (fbevent)-[:ALIGNS_TO]->(baby) | |
---- | |
== What are a user's friends buying? | |
[source, cypher] | |
---- | |
MATCH (user:Person{name: "Alex"})-[:FRIEND]-(friends:Person), | |
(friends)-[:PURCHASED]->(Order)-[:HAS_ITEM]->(items:Item) | |
RETURN length(COLLECT(friends)) AS numPurchases, items.description AS recommendation | |
ORDER BY numPurchases DESC | |
LIMIT 5 | |
---- | |
//table | |
== Match items that align to categories that are aligned to an event. | |
[source, cypher] | |
---- | |
MATCH (items:Item)-[:ALIGNS_TO]->(category:Category)<-[:ALIGNS_TO]-(event:Event{description: "Baby Shower for Meg"}) | |
RETURN items.description as recommendation | |
---- | |
//table | |
== What should I buy for an event honoring a friend? | |
[source, cypher] | |
---- | |
MATCH (event:Event{description: "Baby Shower for Meg"})-[:IS_FOR]->(friend:Person) | |
-[:HAS_INTEREST]->(interest:Interest) | |
-[:ALIGNS_TO]->(category:Category) | |
<-[:ALIGNS_TO]-(items:Item) | |
RETURN items.description AS recommendation | |
ORDER BY items.rating DESC | |
---- | |
//table | |
== Find items in the same category as a specific item. | |
[source, cypher] | |
---- | |
MATCH (item:Item{sku:"070847811169"})-[:ALIGNS_TO]->(category:Category), | |
(suggestItem:Item)-[:ALIGNS_TO]->(category) | |
return item.description as cartItem, suggestItem.description as recommendation, category.name as category,suggestItem.rating as rating | |
ORDER BY rating DESC | |
---- | |
//table | |
== When a user puts an item in their count, you may want to make a recommendation based on what is often purchased at the same time as the cart item. | |
[source, cypher] | |
---- | |
MATCH (pastOrders:PurchaseOrder)-[:HAS_ITEM]->(cartItem:Item{sku:"070847811169"}), | |
(pastOrders)-[:HAS_ITEM]->(itemToSuggest:Item) | |
WITH COLLECT(pastOrders) AS orders, itemToSuggest | |
RETURN LENGTH (orders) AS itemCount,itemToSuggest.description AS recommendation | |
ORDER BY itemCount DESC LIMIT 5 | |
---- | |
//table | |
== When a user purchases an item, you may want to recommend items from the same categories. Notice that an item may align to multiple categories. Here we decide to show the items with the highest ratings. | |
[source, cypher] | |
---- | |
MATCH (item:Item{sku:"070847811169"})-[:ALIGNS_TO]->(category:Category), | |
(suggestItem:Item)-[:ALIGNS_TO]->(category) | |
return suggestItem.description AS description, category.name AS category,suggestItem.rating AS rating | |
ORDER BY rating DESC | |
---- | |
//table | |
== We track the users buying history so we know which categories they tend to buy from. This allows us to recommend items from those categories. | |
[source, cypher] | |
---- | |
MATCH (user{name:"John"})-[:PURCHASED]->(order:PurchaseOrder), | |
(order:PurchaseOrder)-[HAS_ITEM]->(pastItem:Item), | |
(pastItem:Item)-[:ALIGNS_TO]->(pastCategory:Category) | |
WITH pastCategory as pastCats,collect(pastItem) as items | |
RETURN pastCats as category, length(items) | |
ORDER BY length(items) DESC LIMIT 3 | |
---- | |
//table | |
== Suggest an item based on user's history and interests. If a user has a new interest, you may want to do a combination of looking at their history and their current interests to come up with the best recommendation. | |
[source, cypher] | |
---- | |
MATCH (user{name:"John"})-[:PURCHASED]->(order:PurchaseOrder), | |
(order:PurchaseOrder)-[HAS_ITEM]->(pastItem:Item), | |
(pastItem:Item)-[:ALIGNS_TO]->(pastCategory:Category) | |
WHERE NOT HAS(pastItem.giftwrap) | |
WITH pastCategory AS pastCats,collect(pastItem) AS items | |
WITH pastCats | |
ORDER BY length(items) DESC LIMIT 3 | |
MATCH (items:Item)-[:ALIGNS_TO]->(category:Category), | |
(category)<-[:ALIGNS_TO]-(interest:Interest), | |
(user:Person{name:"John"})-[HAS_INTEREST]->(interest), | |
(items)-[:ALIGNS_TO]->(pastCats) | |
WITH items, collect(distinct category) as category | |
ORDER BY items.rating DESC | |
RETURN items.description as recommendation, category | |
---- | |
//table | |
//graph |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment