Skip to content

Instantly share code, notes, and snippets.

@CalvinHarrisUK
Forked from ah3rz/WineGraph
Last active August 29, 2015 13:58
Show Gist options
  • Save CalvinHarrisUK/10111353 to your computer and use it in GitHub Desktop.
Save CalvinHarrisUK/10111353 to your computer and use it in GitHub Desktop.
= 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