Northwind as a Neo4j graph model

A graph data model of Northwind Traders, the fictional specialty foods company, with its customers, orders, products, suppliers, and employees.

Open this model in toro4n The Northwind model in toro4n, with the Layers tab open in the side panel

What the model shows

The model follows Neo4j's Northwind guide, the classic lesson in turning a relational database into a graph: entity tables become labels, and foreign keys and join tables become relationships. A customer purchases each order, an employee sells it, and a shipper ships it. Employees report to a manager and cover sales territories, which belong to regions. Products come from suppliers, belong to categories, and appear on orders.

If you know the relational schema, compare it with the lists below to see where each table and foreign key ended up.

Nodes and properties

Category

Customer

Employee

Order

Product

Region

Shipper

Supplier

Territory

Relationships

Layers

Modeling notes

Cypher

Here's the Cypher script toro4n generates for this model. It starts with property uniqueness and existence constraints, then creates every node and relationship, with each property's type name as a placeholder value. Existence constraints need Neo4j Enterprise Edition or Aura.

CREATE CONSTRAINT Supplier_supplierId_unique IF NOT EXISTS FOR (n:Supplier) REQUIRE n.supplierId IS UNIQUE;
CREATE CONSTRAINT Supplier_supplierId_required IF NOT EXISTS FOR (n:Supplier) REQUIRE n.supplierId IS NOT NULL;
CREATE CONSTRAINT Product_productId_unique IF NOT EXISTS FOR (n:Product) REQUIRE n.productId IS UNIQUE;
CREATE CONSTRAINT Product_productId_required IF NOT EXISTS FOR (n:Product) REQUIRE n.productId IS NOT NULL;
CREATE CONSTRAINT Category_categoryId_unique IF NOT EXISTS FOR (n:Category) REQUIRE n.categoryId IS UNIQUE;
CREATE CONSTRAINT Category_categoryId_required IF NOT EXISTS FOR (n:Category) REQUIRE n.categoryId IS NOT NULL;
CREATE CONSTRAINT Customer_customerId_unique IF NOT EXISTS FOR (n:Customer) REQUIRE n.customerId IS UNIQUE;
CREATE CONSTRAINT Customer_customerId_required IF NOT EXISTS FOR (n:Customer) REQUIRE n.customerId IS NOT NULL;
CREATE CONSTRAINT Order_orderId_unique IF NOT EXISTS FOR (n:Order) REQUIRE n.orderId IS UNIQUE;
CREATE CONSTRAINT Order_orderId_required IF NOT EXISTS FOR (n:Order) REQUIRE n.orderId IS NOT NULL;
CREATE CONSTRAINT Shipper_shipperId_unique IF NOT EXISTS FOR (n:Shipper) REQUIRE n.shipperId IS UNIQUE;
CREATE CONSTRAINT Shipper_shipperId_required IF NOT EXISTS FOR (n:Shipper) REQUIRE n.shipperId IS NOT NULL;
CREATE CONSTRAINT Employee_employeeId_unique IF NOT EXISTS FOR (n:Employee) REQUIRE n.employeeId IS UNIQUE;
CREATE CONSTRAINT Employee_employeeId_required IF NOT EXISTS FOR (n:Employee) REQUIRE n.employeeId IS NOT NULL;
CREATE CONSTRAINT Territory_territoryId_unique IF NOT EXISTS FOR (n:Territory) REQUIRE n.territoryId IS UNIQUE;
CREATE CONSTRAINT Territory_territoryId_required IF NOT EXISTS FOR (n:Territory) REQUIRE n.territoryId IS NOT NULL;
CREATE CONSTRAINT Region_regionId_unique IF NOT EXISTS FOR (n:Region) REQUIRE n.regionId IS UNIQUE;
CREATE CONSTRAINT Region_regionId_required IF NOT EXISTS FOR (n:Region) REQUIRE n.regionId IS NOT NULL;

CREATE (Supplier:Supplier {supplierId: "STRING", companyName: "STRING", contactName: "STRING", contactTitle: "STRING", address: "STRING", city: "STRING", region: "STRING", postalCode: "STRING", country: "STRING", phone: "STRING", fax: "STRING", homePage: "STRING"})
CREATE (Product:Product {productId: "STRING", productName: "STRING", quantityPerUnit: "STRING", unitPrice: "FLOAT", unitsInStock: "INTEGER", unitsOnOrder: "INTEGER", reorderLevel: "INTEGER", discontinued: "BOOLEAN"})
CREATE (Category:Category {categoryId: "STRING", categoryName: "STRING", description: "STRING", picture: "STRING"})
CREATE (Customer:Customer {customerId: "STRING", companyName: "STRING", contactName: "STRING", contactTitle: "STRING", address: "STRING", city: "STRING", region: "STRING", postalCode: "STRING", country: "STRING", phone: "STRING", fax: "STRING"})
CREATE (Order:Order {orderId: "STRING", orderDate: "LOCAL DATETIME", requiredDate: "LOCAL DATETIME", shippedDate: "LOCAL DATETIME", freight: "FLOAT", shipName: "STRING", shipAddress: "STRING", shipCity: "STRING", shipRegion: "STRING", shipPostalCode: "STRING", shipCountry: "STRING"})
CREATE (Shipper:Shipper {shipperId: "STRING", companyName: "STRING", phone: "STRING"})
CREATE (Employee:Employee {employeeId: "STRING", lastName: "STRING", firstName: "STRING", title: "STRING", titleOfCourtesy: "STRING", birthDate: "LOCAL DATETIME", hireDate: "LOCAL DATETIME", address: "STRING", city: "STRING", region: "STRING", postalCode: "STRING", country: "STRING", homePhone: "STRING", extension: "STRING", notes: "STRING", photoPath: "STRING"})
CREATE (Territory:Territory {territoryId: "STRING", territoryDescription: "STRING"})
CREATE (Region:Region {regionId: "STRING", regionDescription: "STRING"})
CREATE (Supplier)-[:SUPPLIES]->(Product)
CREATE (Product)-[:PART_OF]->(Category)
CREATE (Category)-[:PARENT]->(Category)
CREATE (Customer)-[:PURCHASED]->(Order)
CREATE (Order)-[:ORDERS {unitPrice: "FLOAT", quantity: "INTEGER", discount: "FLOAT"}]->(Product)
CREATE (Shipper)-[:SHIPS]->(Order)
CREATE (Employee)-[:SOLD]->(Order)
CREATE (Employee)-[:REPORTS_TO]->(Employee)
CREATE (Employee)-[:IN_TERRITORY]->(Territory)
CREATE (Territory)-[:IN_REGION]->(Region)

Source

The model is based on Neo4j's Northwind Graph guide and the Northwind CSV files. Download the model as northwind.json.