🏆 Graph Challenge 2025 #1 [Ends March 27th at 5PM EST] – Win a cool Neo4j T-Shirt

@kiranu here is your complete entry! Thanks for sending:

This was fun. there you go, my quick and dirty graph...

nestle_graph_fun.png

// Create the Supreme Ruler (Brand)

CREATE (b:Brand {name: "Nestle", motto: "Ruling the Coffee Universe Since Forever"})

// Create the Rebel (Product)

CREATE (p:Product {name: "Coffee Mate", tagline: "Making Coffee Less Boring"})

// Establish the dramatic relationship

CREATE (b)-[:OWNS]->(p)

CREATE (p)-[:BELONGS_TO]->(b)

// Create Flavor Types

CREATE (t1:FlavorType {id: 1, name: "Natural & Artificial Flavor"})

CREATE (t2:FlavorType {id: 2, name: "Artificial Flavor"})

// Create Flavors with Fun Attributes

CREATE (f1:Flavor {id: 101, name: "French Vanilla", personality: "Elegant & Fancy"})

CREATE (f2:Flavor {id: 102, name: "Italian Sweet Creme", personality: "Thinks it's in Rome"})

CREATE (f3:Flavor {id: 103, name: "Irish Creme", personality: "Fake Irish but still fun"})

CREATE (f4:Flavor {id: 104, name: "Hazelnut", personality: "Artificial but lovable"})

// Link Product to Flavors

CREATE (p)-[:HAS_FLAVOR]->(f1)

CREATE (p)-[:HAS_FLAVOR]->(f2)

CREATE (p)-[:HAS_FLAVOR]->(f3)

CREATE (p)-[:HAS_FLAVOR]->(f4)

// Link Flavors to Their True Nature (Flavor Type)

CREATE (f1)-[:HAS_FLAVOR_TYPE]->(t1) // Natural & Artificial

CREATE (f2)-[:HAS_FLAVOR_TYPE]->(t1) // Natural & Artificial

CREATE (f3)-[:HAS_FLAVOR_TYPE]->(t1) // Natural & Artificial

CREATE (f4)-[:HAS_FLAVOR_TYPE]->(t2) // Artificial

// The Almighty Disclaimer (Scary Authority Figure)

CREATE (d:Disclaimer {text: "SHAKE WELL OR ELSE!"})

// The Ever-Present Milk Derivative (Drama Queen)

CREATE (i:Ingredient {name: "Milk Derivative", attitude: "You NEED me!"})

// Chill Storage Guy

CREATE (s:Storage {type: "No Refrigeration Needed", mood: "Chill Vibes Only"})

// UHT Processing - Sounds Mysterious

CREATE (u:UHT {type: "D", mystery: "No one knows what D means"})

// Connect Features to Flavors

CREATE (f1)-[:HAS_DISCLAIMER]->(d)

CREATE (f2)-[:HAS_DISCLAIMER]->(d)

CREATE (f3)-[:HAS_DISCLAIMER]->(d)

CREATE (f4)-[:HAS_DISCLAIMER]->(d)

CREATE (f1)-[:CONTAINS]->(i)

CREATE (f2)-[:CONTAINS]->(i)

CREATE (f3)-[:CONTAINS]->(i)

CREATE (f4)-[:CONTAINS]->(i)

CREATE (f1)-[:HAS_STORAGE_REQUIREMENT]->(s)

CREATE (f2)-[:HAS_STORAGE_REQUIREMENT]->(s)

CREATE (f3)-[:HAS_STORAGE_REQUIREMENT]->(s)

CREATE (f4)-[:HAS_STORAGE_REQUIREMENT]->(s)

CREATE (f1)-[:HAS_UHT_PROCESSING]->(u)

CREATE (f2)-[:HAS_UHT_PROCESSING]->(u)

CREATE (f3)-[:HAS_UHT_PROCESSING]->(u)

CREATE (f4)-[:HAS_UHT_PROCESSING]->(u)

// The Coffee Boss (Distributor)

CREATE (dist:Distributor {name: "Nestle Professional North America", location: "Solon", catchphrase: "We run this coffee game!"})

// Flavors Have Their Own Distributor (Flavors are Proud of Their Origin)

CREATE (f1)-[:DISTRIBUTED_BY]->(dist)

CREATE (f2)-[:DISTRIBUTED_BY]->(dist)

CREATE (f3)-[:DISTRIBUTED_BY]->(dist)

CREATE (f4)-[:DISTRIBUTED_BY]->(dist)

Regards,

Kiran Unnikrishnan

here is my attempt!

My model brings in the colors of the flags of the countries described on the creamer flavors, and allows us to do some cool queries based on where the colors connect the flavor design and the countries flag! See this snip from the Neo4j Browser:

And here is the cypher to create the graph!

CREATE CONSTRAINT unique_Creamer_id IF NOT EXISTS FOR (n:Creamer) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT unique_Flavor_id IF NOT EXISTS FOR (n:Flavor) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT unique_Country_id IF NOT EXISTS FOR (n:Country) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT unique_Color_id IF NOT EXISTS FOR (n:Color) REQUIRE n.id IS UNIQUE;

MERGE (fv:Flavor {id:'FRENCH VANILLA'})
SET fv.colors = ['BLUE', 'SKY BLUE']

WITH *
UNWIND range(0,3) AS iter
CREATE (c:Creamer {id:randomUUID()})
MERGE (c)-[:HAS_FLAVOR]->(fv)
;

MERGE (ic:Flavor {id:'IRISH CREME'})
SET ic.colors = ['GREEN', 'DARK GREEN']
WITH *

UNWIND range(0,2) AS iter
CREATE (c:Creamer {id:randomUUID()})
MERGE (c)-[:HAS_FLAVOR]->(ic)
;

MERGE (isc:Flavor {id:'ITALIAN SWEET CREME'})
SET isc.colors = ['PINK', 'BLACK']
WITH *

UNWIND range(0,1) AS iter
CREATE (c:Creamer {id:randomUUID()})
MERGE (c)-[:HAS_FLAVOR]->(isc)
;

MERGE (hz:Flavor {id:'HAZELNUT'})
SET hz.colors = ['ORANGE', 'YELLOW']
WITH *

UNWIND range(0,3) AS iter
CREATE (c:Creamer {id:randomUUID()})
MERGE (c)-[:HAS_FLAVOR]->(hz)
;

MATCH (fv:Flavor {id:'FRENCH VANILLA'})
MATCH (ic:Flavor {id:'IRISH CREME'})
MATCH (isc:Flavor {id:'ITALIAN SWEET CREME'})

MERGE (ir:Country {id:'IRELAND'})
SET ir.flagColors = ['GREEN','WHITE','ORANGE']

MERGE (fr:Country {id:'FRANCE'})
SET fr.flagColors = ['RED','WHITE','BLUE']

MERGE (it:Country {id:'ITALY'})
SET it.flagColors = ['RED','WHITE','GREEN']

MERGE (fv)-[:ORIGINATES_FROM]->(fr)
MERGE (ic)-[:ORIGINATES_FROM]->(ir)
MERGE (isc)-[:ORIGINATES_FROM]->(it);

MATCH (fv:Flavor)
UNWIND fv.colors AS color
MERGE (c:Color{id:color})
MERGE (fv)-[:HAS_COLOR]->(c);

MATCH (co:Country)
UNWIND co.flagColors AS color
MERGE (c:Color{id:color})
MERGE (co)-[:HAS_COLOR]->(c);

Also if you want to add some QPP Action :wink: this is getting the longest color connection path

MATCH p=()-[:HAS_COLOR]-+() 
WITH p, length(p) AS len 
RETURN p 
ORDER BY len DESC LIMIT 1;

This is getting really really good!

Hi, great challenge!

Here goes my attempt:

Here are the queries to create the graph:

// Define node labels and their properties using MERGE for idempotent execution

// Product node (Coffee-mate brand)
MERGE (brand:Brand {name: "Coffee-mate"})
ON CREATE SET brand.manufacturer = "Nestlé"

// Region/Country nodes
MERGE (france:Region {name: "France"})
ON CREATE SET france.type = "Country", france.continent = "Europe"

MERGE (italy:Region {name: "Italy"})
ON CREATE SET italy.type = "Country", italy.continent = "Europe"

MERGE (ireland:Region {name: "Ireland"})
ON CREATE SET ireland.type = "Country", ireland.continent = "Europe"

// Flavor nodes
MERGE (hazelnut:Flavor {name: "Hazelnut"})
ON CREATE SET hazelnut.type = "Nut", hazelnut.isArtificial = true

MERGE (frenchVanilla:Flavor {name: "French Vanilla"})
ON CREATE SET frenchVanilla.type = "Vanilla", frenchVanilla.isArtificial = true, frenchVanilla.isNatural = true

MERGE (italianCreme:Flavor {name: "Italian Sweet Creme"})
ON CREATE SET italianCreme.type = "Cream", italianCreme.isArtificial = true

MERGE (irishCreme:Flavor {name: "Irish Creme"})
ON CREATE SET irishCreme.type = "Cream", irishCreme.isArtificial = true

// Ingredient nodes
MERGE (milk:Ingredient {name: "Milk Derivative"})
MERGE (sugar:Ingredient {name: "Sugar"})
MERGE (vegetableOil:Ingredient {name: "Vegetable Oil"})

// Packaging nodes
MERGE (singleServe:Packaging {type: "Single Serve"})
ON CREATE SET singleServe.material = "Plastic"

// Product type nodes
MERGE (hazelnutCreamer:ProductType {name: "Hazelnut Coffee Creamer"})
ON CREATE SET hazelnutCreamer.sku = "CM-HZ-001"

MERGE (frenchVanillaCreamer:ProductType {name: "French Vanilla Coffee Creamer"})
ON CREATE SET frenchVanillaCreamer.sku = "CM-FV-001"

MERGE (italianCremeCreamer:ProductType {name: "Italian Sweet Creme Coffee Creamer"})
ON CREATE SET italianCremeCreamer.sku = "CM-IC-001"

MERGE (irishCremeCreamer:ProductType {name: "Irish Creme Coffee Creamer"})
ON CREATE SET irishCremeCreamer.sku = "CM-IRC-001"

// Storage nodes
MERGE (refrigeration:StorageRequirement {type: "Refrigeration"})
ON CREATE SET refrigeration.temperature = "Below 40°F"

// Dietary notes
MERGE (lactose:DietaryNote {type: "Contains Lactose"})
MERGE (shakeWell:Instruction {instruction: "Shake Well"})

// Create relationships between nodes for product types

// Brand to Product Types
MERGE (brand)-[:PRODUCES]->(hazelnutCreamer)
MERGE (brand)-[:PRODUCES]->(frenchVanillaCreamer)
MERGE (brand)-[:PRODUCES]->(italianCremeCreamer)
MERGE (brand)-[:PRODUCES]->(irishCremeCreamer)

// Product Types to Flavors
MERGE (hazelnutCreamer)-[:HAS_FLAVOR]->(hazelnut)
MERGE (frenchVanillaCreamer)-[:HAS_FLAVOR]->(frenchVanilla)
MERGE (italianCremeCreamer)-[:HAS_FLAVOR]->(italianCreme)
MERGE (irishCremeCreamer)-[:HAS_FLAVOR]->(irishCreme)

// Flavors to Regions
MERGE (frenchVanilla)-[:INSPIRED_BY]->(france)
MERGE (italianCreme)-[:INSPIRED_BY]->(italy)
MERGE (irishCreme)-[:INSPIRED_BY]->(ireland)

// Product Types to Ingredients
MERGE (hazelnutCreamer)-[:CONTAINS]->(milk)
MERGE (hazelnutCreamer)-[:CONTAINS]->(sugar)
MERGE (hazelnutCreamer)-[:CONTAINS]->(vegetableOil)
MERGE (frenchVanillaCreamer)-[:CONTAINS]->(milk)
MERGE (frenchVanillaCreamer)-[:CONTAINS]->(sugar)
MERGE (frenchVanillaCreamer)-[:CONTAINS]->(vegetableOil)
MERGE (italianCremeCreamer)-[:CONTAINS]->(milk)
MERGE (italianCremeCreamer)-[:CONTAINS]->(sugar)
MERGE (italianCremeCreamer)-[:CONTAINS]->(vegetableOil)
MERGE (irishCremeCreamer)-[:CONTAINS]->(milk)
MERGE (irishCremeCreamer)-[:CONTAINS]->(sugar)
MERGE (irishCremeCreamer)-[:CONTAINS]->(vegetableOil)

// Product Types to Packaging
MERGE (hazelnutCreamer)-[:PACKAGED_IN]->(singleServe)
MERGE (frenchVanillaCreamer)-[:PACKAGED_IN]->(singleServe)
MERGE (italianCremeCreamer)-[:PACKAGED_IN]->(singleServe)
MERGE (irishCremeCreamer)-[:PACKAGED_IN]->(singleServe)

// Product Types to Storage Requirements
MERGE (hazelnutCreamer)-[:REQUIRES]->(refrigeration)
MERGE (frenchVanillaCreamer)-[:REQUIRES]->(refrigeration)
MERGE (italianCremeCreamer)-[:REQUIRES]->(refrigeration)
MERGE (irishCremeCreamer)-[:REQUIRES]->(refrigeration)

// Product Types to Instructions
MERGE (hazelnutCreamer)-[:INSTRUCTION]->(shakeWell)
MERGE (frenchVanillaCreamer)-[:INSTRUCTION]->(shakeWell)
MERGE (italianCremeCreamer)-[:INSTRUCTION]->(shakeWell)
MERGE (irishCremeCreamer)-[:INSTRUCTION]->(shakeWell)

// Product Types to Dietary Notes
MERGE (hazelnutCreamer)-[:DIETARY_NOTE]->(lactose)
MERGE (frenchVanillaCreamer)-[:DIETARY_NOTE]->(lactose)
MERGE (italianCremeCreamer)-[:DIETARY_NOTE]->(lactose)
MERGE (irishCremeCreamer)-[:DIETARY_NOTE]->(lactose)

// Individual CoffeeMate creamer units
// Based on the image, create individual creamer unit nodes with unique IDs

// Hazelnut creamer units (3 units in the image)
MERGE (hz1:CreamerUnit {id: "HZ-001"})
ON CREATE SET hz1.productionDate = "2025-01-15"
MERGE (hz1)-[:IS_TYPE_OF]->(hazelnutCreamer)

MERGE (hz2:CreamerUnit {id: "HZ-002"})
ON CREATE SET hz2.productionDate = "2025-01-15"
MERGE (hz2)-[:IS_TYPE_OF]->(hazelnutCreamer)

MERGE (hz3:CreamerUnit {id: "HZ-003"})
ON CREATE SET hz3.productionDate = "2025-01-16"
MERGE (hz3)-[:IS_TYPE_OF]->(hazelnutCreamer)

// French Vanilla creamer units (4 units in the image)
MERGE (fv1:CreamerUnit {id: "FV-001"})
ON CREATE SET fv1.productionDate = "2025-01-10"
MERGE (fv1)-[:IS_TYPE_OF]->(frenchVanillaCreamer)

MERGE (fv2:CreamerUnit {id: "FV-002"})
ON CREATE SET fv2.productionDate = "2025-01-10"
MERGE (fv2)-[:IS_TYPE_OF]->(frenchVanillaCreamer)

MERGE (fv3:CreamerUnit {id: "FV-003"})
ON CREATE SET fv3.productionDate = "2025-01-11"
MERGE (fv3)-[:IS_TYPE_OF]->(frenchVanillaCreamer)

MERGE (fv4:CreamerUnit {id: "FV-004"})
ON CREATE SET fv4.productionDate = "2025-01-11"
MERGE (fv4)-[:IS_TYPE_OF]->(frenchVanillaCreamer)

// Italian Sweet Creme creamer units (4 units in the image)
MERGE (ic1:CreamerUnit {id: "IC-001"})
ON CREATE SET ic1.productionDate = "2025-01-12"
MERGE (ic1)-[:IS_TYPE_OF]->(italianCremeCreamer)

MERGE (ic2:CreamerUnit {id: "IC-002"})
ON CREATE SET ic2.productionDate = "2025-01-12" 
MERGE (ic2)-[:IS_TYPE_OF]->(italianCremeCreamer)

MERGE (ic3:CreamerUnit {id: "IC-003"})
ON CREATE SET ic3.productionDate = "2025-01-13"
MERGE (ic3)-[:IS_TYPE_OF]->(italianCremeCreamer)

MERGE (ic4:CreamerUnit {id: "IC-004"})
ON CREATE SET ic4.productionDate = "2025-01-13"
MERGE (ic4)-[:IS_TYPE_OF]->(italianCremeCreamer)

// Irish Creme creamer units (3 units in the image)
MERGE (irc1:CreamerUnit {id: "IRC-001"})
ON CREATE SET irc1.productionDate = "2025-01-14"
MERGE (irc1)-[:IS_TYPE_OF]->(irishCremeCreamer)

MERGE (irc2:CreamerUnit {id: "IRC-002"})
ON CREATE SET irc2.productionDate = "2025-01-14"
MERGE (irc2)-[:IS_TYPE_OF]->(irishCremeCreamer)

MERGE (irc3:CreamerUnit {id: "IRC-003"})
ON CREATE SET irc3.productionDate = "2025-01-15"
MERGE (irc3)-[:IS_TYPE_OF]->(irishCremeCreamer)

// Spatial relationships between creamer units based on the image
// These relationships represent which creamers are adjacent to each other in the photo
// Creating [:ADJACENT_TO] relationships to represent spatial proximity

// Using MERGE for each relationship to ensure they're created only once

// Center of the arrangement has the most connections
// Looking at the image, there appears to be a central French Vanilla unit (fv3) with many connections

// Hazelnut adjacency relationships
MERGE (hz1)-[:ADJACENT_TO]->(fv1)
MERGE (hz1)-[:ADJACENT_TO]->(hz2)
MERGE (hz1)-[:ADJACENT_TO]->(fv2)

MERGE (hz2)-[:ADJACENT_TO]->(hz1)
MERGE (hz2)-[:ADJACENT_TO]->(fv2)
MERGE (hz2)-[:ADJACENT_TO]->(ic1)
MERGE (hz2)-[:ADJACENT_TO]->(hz3)

MERGE (hz3)-[:ADJACENT_TO]->(hz2)
MERGE (hz3)-[:ADJACENT_TO]->(ic1)
MERGE (hz3)-[:ADJACENT_TO]->(ic2)

// French Vanilla adjacency relationships
MERGE (fv1)-[:ADJACENT_TO]->(hz1)
MERGE (fv1)-[:ADJACENT_TO]->(fv2)
MERGE (fv1)-[:ADJACENT_TO]->(fv3)

MERGE (fv2)-[:ADJACENT_TO]->(fv1)
MERGE (fv2)-[:ADJACENT_TO]->(hz1)
MERGE (fv2)-[:ADJACENT_TO]->(hz2)
MERGE (fv2)-[:ADJACENT_TO]->(fv3)
MERGE (fv2)-[:ADJACENT_TO]->(ic1)

MERGE (fv3)-[:ADJACENT_TO]->(fv1)
MERGE (fv3)-[:ADJACENT_TO]->(fv2)
MERGE (fv3)-[:ADJACENT_TO]->(ic1)
MERGE (fv3)-[:ADJACENT_TO]->(ic4)
MERGE (fv3)-[:ADJACENT_TO]->(fv4)
MERGE (fv3)-[:ADJACENT_TO]->(irc1)

MERGE (fv4)-[:ADJACENT_TO]->(fv3)
MERGE (fv4)-[:ADJACENT_TO]->(irc1)
MERGE (fv4)-[:ADJACENT_TO]->(ic4)
MERGE (fv4)-[:ADJACENT_TO]->(irc2)

// Italian Sweet Creme adjacency relationships
MERGE (ic1)-[:ADJACENT_TO]->(hz2)
MERGE (ic1)-[:ADJACENT_TO]->(hz3)
MERGE (ic1)-[:ADJACENT_TO]->(fv2)
MERGE (ic1)-[:ADJACENT_TO]->(fv3)
MERGE (ic1)-[:ADJACENT_TO]->(ic2)
MERGE (ic1)-[:ADJACENT_TO]->(ic4)

MERGE (ic2)-[:ADJACENT_TO]->(hz3)
MERGE (ic2)-[:ADJACENT_TO]->(ic1)
MERGE (ic2)-[:ADJACENT_TO]->(ic3)
MERGE (ic2)-[:ADJACENT_TO]->(ic4)

MERGE (ic3)-[:ADJACENT_TO]->(ic2)
MERGE (ic3)-[:ADJACENT_TO]->(ic4)
MERGE (ic3)-[:ADJACENT_TO]->(irc2)
MERGE (ic3)-[:ADJACENT_TO]->(irc3)

MERGE (ic4)-[:ADJACENT_TO]->(ic1)
MERGE (ic4)-[:ADJACENT_TO]->(ic2)
MERGE (ic4)-[:ADJACENT_TO]->(ic3)
MERGE (ic4)-[:ADJACENT_TO]->(fv3)
MERGE (ic4)-[:ADJACENT_TO]->(fv4)
MERGE (ic4)-[:ADJACENT_TO]->(irc1)
MERGE (ic4)-[:ADJACENT_TO]->(irc2)

// Irish Creme adjacency relationships
MERGE (irc1)-[:ADJACENT_TO]->(fv3)
MERGE (irc1)-[:ADJACENT_TO]->(fv4)
MERGE (irc1)-[:ADJACENT_TO]->(ic4)
MERGE (irc1)-[:ADJACENT_TO]->(irc2)

MERGE (irc2)-[:ADJACENT_TO]->(irc1)
MERGE (irc2)-[:ADJACENT_TO]->(fv4)
MERGE (irc2)-[:ADJACENT_TO]->(ic4)
MERGE (irc2)-[:ADJACENT_TO]->(ic3)
MERGE (irc2)-[:ADJACENT_TO]->(irc3)

MERGE (irc3)-[:ADJACENT_TO]->(irc2)
MERGE (irc3)-[:ADJACENT_TO]->(ic3)

Here are some sample queries:

// Sample queries to retrieve information

// Count the number of creamer units by flavor
MATCH (cu:CreamerUnit)-[:IS_TYPE_OF]->(pt:ProductType)-[:HAS_FLAVOR]->(f:Flavor)
RETURN f.name AS Flavor, COUNT(cu) AS UnitCount
ORDER BY UnitCount DESC

// Count the number of creamer units by product type
MATCH (cu:CreamerUnit)-[:IS_TYPE_OF]->(pt:ProductType)
RETURN pt.name AS ProductType, COUNT(cu) AS UnitCount
ORDER BY UnitCount DESC

// Find all flavors of Coffee-mate products
MATCH (b:Brand {name: "Coffee-mate"})-[:PRODUCES]->(pt:ProductType)-[:HAS_FLAVOR]->(f:Flavor)
RETURN pt.name AS ProductType, f.name AS Flavor

// Find all products with flavors inspired by European regions
MATCH (pt:ProductType)-[:HAS_FLAVOR]->(f:Flavor)-[:INSPIRED_BY]->(r:Region {continent: "Europe"})
RETURN pt.name AS ProductType, f.name AS Flavor, r.name AS Region

// Count how many creamer units have flavors inspired by each region
MATCH (cu:CreamerUnit)-[:IS_TYPE_OF]->(pt:ProductType)-[:HAS_FLAVOR]->(f:Flavor)-[:INSPIRED_BY]->(r:Region)
RETURN r.name AS Region, COUNT(cu) AS CreamerCount
ORDER BY CreamerCount DESC

// Find the most common flavor in the collection
MATCH (cu:CreamerUnit)-[:IS_TYPE_OF]->(pt:ProductType)-[:HAS_FLAVOR]->(f:Flavor)
RETURN f.name AS Flavor, COUNT(cu) AS Count
ORDER BY Count DESC
LIMIT 1

// Find all creamer units adjacent to a specific unit
MATCH (cu:CreamerUnit {id: "FV-001"})-[:ADJACENT_TO]->(adjacent:CreamerUnit)
RETURN cu.id AS Unit, adjacent.id AS AdjacentUnit

// Count how many adjacent units each creamer has
MATCH (cu:CreamerUnit)-[:ADJACENT_TO]->(adjacent:CreamerUnit)
RETURN cu.id AS CreamerUnit, COUNT(adjacent) AS AdjacentCount
ORDER BY AdjacentCount DESC

// Find clusters of creamers (units that form groups based on adjacency)
MATCH path = (start:CreamerUnit)-[:ADJACENT_TO*1..14]-(connected:CreamerUnit)
WHERE id(start) < id(connected)
RETURN start.id AS StartUnit, collect(connected.id) AS ConnectedUnits

// Find units with the most adjacent neighbors
MATCH (cu:CreamerUnit)-[:ADJACENT_TO]->(adjacent:CreamerUnit)
RETURN cu.id AS UnitID, 
       [(cu)-[:IS_TYPE_OF]->(pt:ProductType)-[:HAS_FLAVOR]->(f:Flavor) | f.name][0] AS Flavor,
       COUNT(adjacent) AS ConnectionCount
ORDER BY ConnectionCount DESC
LIMIT 5

// Identify the most central creamer unit (highest degree centrality)
MATCH (cu:CreamerUnit)
OPTIONAL MATCH (cu)-[:ADJACENT_TO]->(neighbor:CreamerUnit)
WITH cu, COUNT(neighbor) AS degree
RETURN cu.id AS UnitID,
       [(cu)-[:IS_TYPE_OF]->(pt:ProductType)-[:HAS_FLAVOR]->(f:Flavor) | f.name][0] AS Flavor,
       degree AS Centrality
ORDER BY Centrality DESC
LIMIT 1

// Find which flavor has the most connections to other flavors
MATCH (cu1:CreamerUnit)-[:IS_TYPE_OF]->(pt1:ProductType)-[:HAS_FLAVOR]->(f1:Flavor),
      (cu1)-[:ADJACENT_TO]->(cu2:CreamerUnit)-[:IS_TYPE_OF]->(pt2:ProductType)-[:HAS_FLAVOR]->(f2:Flavor)
WHERE f1 <> f2
RETURN f1.name AS Flavor, COUNT(DISTINCT f2) AS ConnectedToOtherFlavors
ORDER BY ConnectedToOtherFlavors DESC

Cyphers to create graph:

CREATE (:CoffeeShop { javaId: '1', name: 'CoffeeShop' });
CREATE (:Table { javaId: '1', name: 'Table', material: 'Wood' });
CREATE (:Bowl { javaId: '1', name: 'Bowl', material: 'Ceramic' });
CREATE (:Brand { javaId: '1', name: 'Nestle', country: 'USA' });

CREATE (:CoffeeType { javaId: '1', name: 'Coffee' });
CREATE (:CoffeeType { javaId: '2', name: 'Latte' });
CREATE (:CoffeeType { javaId: '3', name: 'Cappuccino' });
CREATE (:CoffeeType { javaId: '4', name: 'Americano' });

CREATE (:Creamer { javaId: '1', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025' });
CREATE (:Creamer { javaId: '2', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '3', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '4', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '5', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '6', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '7', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '8', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '9', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '10', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '11', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '12', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '13', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });
CREATE (:Creamer { javaId: '14', name: 'CoffeeMate', volume: '10ml', requiresShaking: true, requiresRefrigeration: true, expiryDate: '03-27-2025'  });

CREATE (:Flavour { javaId: '1', name: 'Irish Cream' });
CREATE (:Flavour { javaId: '2', name: 'Hazelnut' });
CREATE (:Flavour { javaId: '3', name: 'French Vanilla' });
CREATE (:Flavour { javaId: '4', name: 'Italian Sweet Creme' });

MATCH (a:CoffeeShop { javaId: '1'})
MATCH (b:Table { javaId: '1'})
MERGE (a)-[:HAS_CONTENTS]->(b);

MATCH (a:Table { javaId: '1'})
MATCH (b:Bowl { javaId: '1'})
MERGE (a)-[:HAS_CONTENTS]->(b);

MATCH (a:Bowl { javaId: '1'})
MATCH (b:Creamer) WHERE b.javaId IN ['1','2','3','4','5','6','7','8','9','10','11','12','13','14']
MERGE (a)-[:HAS_CONTENTS]->(b);

MATCH (a:Brand { javaId: '1'})
MATCH (b:Creamer) WHERE b.javaId IN ['1','2','3','4','5','6','7','8','9','10','11','12','13','14']
MERGE (b)-[:CREATED_BY]->(a);

MATCH (a:Flavour { javaId: '1'})
MATCH (b:Creamer) WHERE b.javaId IN ['1','2','3']
MERGE (b)-[:HAS_FLAVOUR]->(a);

MATCH (a:Flavour { javaId: '2'})
MATCH (b:Creamer) WHERE b.javaId IN ['4','5','6','7']
MERGE (b)-[:HAS_FLAVOUR]->(a);

MATCH (a:Flavour { javaId: '3'})
MATCH (b:Creamer) WHERE b.javaId IN ['8','9','10','11']
MERGE (b)-[:HAS_FLAVOUR]->(a);

MATCH (a:Flavour { javaId: '4'})
MATCH (b:Creamer) WHERE b.javaId IN ['12','13','14']
MERGE (b)-[:HAS_FLAVOUR]->(a);

MATCH (a:CoffeeType { javaId: '1'})
MATCH (b:Flavour) WHERE b.javaId IN ['1','2']
MERGE (a)-[:PAIRS_WELL_WITH]->(b);

MATCH (a:CoffeeType { javaId: '2'})
MATCH (b:Flavour) WHERE b.javaId = '4'
MERGE (a)-[:PAIRS_WELL_WITH]->(b);

MATCH (a:CoffeeType { javaId: '3'})
MATCH (b:Flavour) WHERE b.javaId IN ['2','3']
MERGE (a)-[:PAIRS_WELL_WITH]->(b);

MATCH (a:CoffeeType { javaId: '4'})
MATCH (b:Flavour) WHERE b.javaId IN ['1','2','3','4']
MERGE (a)-[:PAIRS_WELL_WITH]->(b);

This graph covers two areas of interest:

  1. The physical inventory of the coffee shop(only what is shown in the image)
  2. How the creamers relate to coffee types

From left to right in the graph, we have a CoffeeShop node representing the coffee shop itself, which has a Table. The table has a Bowl, which contains the 14 Creamers. The same HAS_CONTENTS relationship is used for the entire physical inventory hierarchy to make downstream deep traversal easier with the variable length path.

Each Creamer has some properties, and a relationship to its creator Nestle. The creamers are also related to specific Flavours(i.e. French Vanilla, Irish Creme etc.). Each Flavour has a relationship to a type of coffee with which it "pairs well" with.

See the attached cypher file for the properties associated with each node type. I used "javaId" as the unique identifier of each node.

Below are some cyphers to query the physical inventory, and coffee related data:

Get all of the downstream physical contents starting from the Table

MATCH path=(t:Table)-[:HAS_CONTENTS*]->(contents)
WHERE t.javaId = '1'
RETURN contents

Get all Creamers that have Irish Creme flavour

MATCH (c:Creamer)-[:HAS_FLAVOUR]->(f:Flavour)
WHERE f.name = 'Irish Cream'
RETURN c

Get all Flavours that pair well with Cappuccino

MATCH (f:Flavour)<-[:PAIRS_WELL_WITH]-(c:CoffeeType)
WHERE c.name = 'Cappuccino'
RETURN f

Get all Creamers that have Flavours that pair well with Coffee

MATCH (c:Creamer)-[:HAS_FLAVOUR]->(f:Flavour)<-[:PAIRS_WELL_WITH]-(ct:CoffeeType)
WHERE ct.name = 'Coffee'
RETURN c

Get the CoffeeType(s) that pair well with the most Flavours

MATCH (ct:CoffeeType)-[r:PAIRS_WELL_WITH]->(f:Flavour)
WITH ct, COUNT(r) AS relCount
ORDER BY relCount DESC
WITH COLLECT({ node: ct, count: relCount }) AS nodes
RETURN [n IN nodes WHERE n.count = nodes[0].count] AS topCoffeeTypes

Hi Ari

My first ever submission to a contest :crossed_fingers:

I have attached a pdf

Thanks
Nawar

(Attachment neo4j_contest.pdf is missing)

@nawar.alwesh - I love it! CoffeeMate is a pretty powerful draw :hot_beverage:.

I don't think the PDF was attached - can you submit graph image?

Hi Ari

My first ever submission to a contest :crossed_fingers:

I have attached the images since couldn't attach a pdf

Thanks
Nawar

(attachments)








I got it now. Thank you!

Hi, a simple graph. Just to play around with.

here is my contribution, maybe a bit different take

/**
In this vibrant, hierarchical ecosystem,
Species define lineage and purity; Subspecies express subtle variation.
Life arranges itself in layers — Canopy, Understory, and Forest Floor — each a distinct stratum,
which in turn is part of the nurturing Sanctuary resting upon the Foundation.
Creatures (Specimens) reside within these layers, never directly upon the whole,
reflecting nature’s beautifully ordered hierarchy.
*/

// Create the Foundation and Sanctuary
MERGE (foundation:Foundation {name: 'Foundation'})
  ON CREATE SET foundation.description = 'A vast and steady plane, upon which the delicate balance of this small ecosystem rests.'

MERGE (sanctuary:Sanctuary {name: 'Sanctuary'})
  ON CREATE SET sanctuary.description = 'A protective hollow where diverse species find safe gathering and harmonious shelter.'

MERGE (foundation)-[:SUPPORTS]->(sanctuary)

// Create Layers and associate them with the Sanctuary
MERGE (canopy:Layer {name: 'Canopy'})-[:PART_OF]->(sanctuary)
MERGE (understory:Layer {name: 'Understory'})-[:PART_OF]->(sanctuary)
MERGE (forestFloor:Layer {name: 'Forest Floor'})-[:PART_OF]->(sanctuary)

// Create Purity categories
MERGE (pureNatural:Purity {name: 'Natural & Artificial'})
MERGE (pureArtificial:Purity {name: 'Artificial Only'})

// Create Species and assign purity
MERGE (hazelnut:Species {name: 'Hazelnut'})-[:HAS_PURITY]->(pureArtificial)
MERGE (frenchVanilla:Species {name: 'French Vanilla'})-[:HAS_PURITY]->(pureNatural)
MERGE (irishCreme:Species {name: 'Irish Creme'})-[:HAS_PURITY]->(pureNatural)
MERGE (italianCreme:Species {name: 'Italian Sweet Creme'})-[:HAS_PURITY]->(pureNatural)

// Create Subspecies
MERGE (hzBright:Subspecies {name: 'Hazelnut Bright'})-[:HAS_SUBSPECIES_OF]->(hazelnut)
MERGE (hzMuted:Subspecies {name: 'Hazelnut Muted'})-[:HAS_SUBSPECIES_OF]->(hazelnut)
MERGE (fvBright:Subspecies {name: 'French Vanilla Bright'})-[:HAS_SUBSPECIES_OF]->(frenchVanilla)
MERGE (fvDeep:Subspecies {name: 'French Vanilla Deep'})-[:HAS_SUBSPECIES_OF]->(frenchVanilla)
MERGE (iscPure:Subspecies {name: 'Italian Sweet Creme'})-[:HAS_SUBSPECIES_OF]->(italianCreme)
MERGE (icPure:Subspecies {name: 'Irish Creme'})-[:HAS_SUBSPECIES_OF]->(irishCreme)

// Assign each Specimen with poetic name, subspecies, and layer
FOREACH (entry IN [
  ['AmberDrifter', 'Hazelnut Bright', 'Canopy'],
  ['GoldenHaven', 'Hazelnut Muted', 'Understory'],
  ['Rustleaf', 'Hazelnut Muted', 'Understory'],
  ['AutumnGlow', 'Hazelnut Bright', 'Canopy'],
  ['EmeraldPulse', 'Irish Creme', 'Canopy'],
  ['VerdantCharm', 'Irish Creme', 'Understory'],
  ['MeadowSpirit', 'Irish Creme', 'Understory'],
  ['SilkenWisp', 'French Vanilla Bright', 'Canopy'],
  ['CreamFeather', 'French Vanilla Bright', 'Canopy'],
  ['VanillaBreeze', 'French Vanilla Deep', 'Understory'],
  ['SoftAurora', 'French Vanilla Deep', 'Understory'],
  ['PetalWhisper', 'Italian Sweet Creme', 'Canopy'],
  ['Roselight', 'Italian Sweet Creme', 'Understory'],
  ['VelvetBlush', 'Italian Sweet Creme', 'Understory'],
  ['BlossomGleam', 'Italian Sweet Creme', 'Forest Floor'],
  ['AzureDrift', 'French Vanilla Bright', 'Forest Floor'],
  ['SkyMist', 'French Vanilla Bright', 'Forest Floor'],
  ['CreamNest', 'Italian Sweet Creme', 'Forest Floor']
] |
MERGE (s:Specimen {name: entry[0]})
MERGE (sub:Subspecies {name: entry[1]})
MERGE (layer:Layer {name: entry[2]})
MERGE (s)-[:BELONGS_TO_SUBSPECIES]->(sub)
MERGE (s)-[:RESIDES_IN]->(layer)
)

We love "different"! Thanks @bengt.ellison

Here is a little fun project. I've created a KG in AuraDB from this image by extracting nodes and relationships using an LLM. Here is the Jupyter Notebook: https://github.com/pwrose/neo4j-graph-contest/blob/main/notebooks/contest1.ipynb.

Btw, how can I increase the font size for the relationships?

-Peter

Wow! This is great Peter - I will get you the answer to that question.

Hi Ari,

Enclosed is a screenshot from my graph visualizer, which you can see is a 3D display.

The nodes are really simple:
create (a:Additive { name:(whatever), color:(whatever)})
I only used the predominant color for each flavor, as doing that two tone swirl is quite a bit more work.
There’s a base node named Coffeemate, and each node instance is connected to that.
There’s one node glowing because it’s the current selection, which you can see is Irish Creme.

Best regards,

Dr. Julian E Gómez ** www.polished-pixels.com ** @3dscientist.bsky.social

:tada: The Wait is Almost Over... :tada:
:drum: The drumroll drops TOMORROW at 5PM EST!

:t_shirt::collision: We’re revealing the Official T-Shirt Prize for ** Graph Challenge 2025 #1** – and trust us, you’re going to want one. It’s fresh. It’s fun. It’s graph-powered.

:glowing_star: But that’s not all...

:trophy: **The WINNER ** will also be announced!

Our notorious and fearless judge, @abk, has reviewed the submissions and selected a champion based on:

:sparkles: Creativity
:brain: Clarity
:spider_web: Graph-y Goodness

:shushing_face: Who will claim eternal bragging rights (and some sweet Neo4j swag)?
You’ll find out right here — same thread, same time.

Set your reminders. Bring popcorn. This one’s gonna be fun. :popcorn::fire:


This contest was not sponsored by Nestlé CoffeeMate — but let’s be honest, they probably would’ve if we asked. :wink:

:hourglass_not_done: A Tiny Delay... But Totally Worth It!

Hey everyone! :waving_hand:
We’re running a little behind on announcing the winner of our Graph Challenge — oops! :sweat_smile:

There were so many fun and creative entries - 15 in total - that we want to give each one the proper love and attention it deserves (and yes, a few of us may have gotten sidetracked in the Cypher wormhole :repeat_button:).

:speech_balloon: Good news: Judging is in progress and we’ll be announcing the winner very soon!

Bonus twist: To make up for the wait, we’re also awarding a surprise second-place shout-out this round — because this community seriously brought the graph energy. :collision:

Thanks for your patience — and stay tuned, we’ll be back shortly with the results! :raising_hands:

  • Ari

:drum: Drumroll Please…

We have a WINNER for our very first ** Graph Challenge 2025 **! :brain::tada:

According to our judge @abk:

"The winner was an entry noted for an all-around high level of detail, creativity, and graphiness. They also included a PDF addendum with impressive details on scene, schema, and instances — even coordinate positioning and angles. Top marks!"

:clap::clap::clap:

:trophy: Please join us in congratulating... @nawar.alwesh!

Their approach stood out not just for solid graph thinking, but also for the extra polish and thought that went into every detail. :exploding_head:


:paperclip: Winning entry:
Click here to view it

:t_shirt: Prize: One very cool Neo4j t-shirt is headed your way!

Our very own coveted DevRel Sci-Fi Themed Design. [@nawar.alwesh - DM me your address and phone number so we can ship this out to you! ASAP!]

A special shout out as promised, goes to our two runner-ups tied for 2nd place:

@Kirsten_Langendorf and @codefishdj — awesome submissions!

Thanks to everyone who participated — the creativity from this community is truly inspiring. The next challenge drops soon, and who knows... YOU could be next! New challenge will be posted Monday!:collision:

#Neo4jGraphChallenge #Winner #Neo4jCommunity

3 Likes