Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions asciidoc/courses/importing-relational-to-graph/ad.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:page-ad-title: Learn how to import relational data into Neo4j with GraphAcademy
:page-ad-description: This 3-hours course explores the options for importing data into Neo4j.
:page-ad-link: https://graphacademy.neo4j.com/courses/importing-fundamentals/?ref=docs-ad-importing-fundamentals
:page-ad-underline-role: button
:page-ad-underline: Enroll for free
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions asciidoc/courses/importing-relational-to-graph/course.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
= Importing Relational Data into Neo4j
:categories: beginners:4, start:4, data-analysis:4, reporting:4, software-development:4, foundation:4
:status: active
:next: importing-cypher
:duration: 3 hours
:caption: Learn how to import relational SQL data into Neo4j
:usecase: blank-sandbox
:key-points: Migrating from relational to graph databases, Transforming SQL data models, Using Neo4j Data Importer, Working with PostgreSQL and Northwind


== Course Description

Welcome to Importing Relational Data into Neo4j!

In this course, you will learn how to migrate data from relational databases into Neo4j. You will work with the classic Northwind PostgreSQL database and transform it into a graph data model optimized for traversal queries.

You will learn to:

* Understand the fundamental differences between relational and graph data models.
* Analyze relational database schemas to identify entities, relationships, and properties.
* Use PostgreSQL and Postico or pgAdmin to explore and query relational data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Postgres is where the data happens to come from, we shouldn't be teaching them how to use Postico or pgAdmin.

* Transform relational tables into graph nodes and relationships.
* Use the Neo4j Data Importer to import relational data into a Neo4j Aura instance.
* Set unique IDs, constraints, and indexes to ensure data quality and query performance.

You will work hands-on with the Northwind database, a sample relational database representing a fictional company's sales data, and migrate it into a graph structure that you can query using Cypher.


=== Prerequisites

Before taking this course, you should have an understanding of:

* Graph and Neo4j fundamental concepts
* Basic Cypher queries
* Relational database concepts and SQL
* Graph data modeling principles

Completing the following courses in GraphAcademy is recommended:

* link:https://graphacademy.neo4j.com/courses/neo4j-fundamentals/[Neo4j Fundamentals^]
* link:https://graphacademy.neo4j.com/courses/cypher-fundamentals/[Cypher Fundamentals^]
* link:https://graphacademy.neo4j.com/courses/modeling-fundamentals/[Graph Data Modeling Fundamentals^]

You will also need:

* A Neo4j database - choose one of:
** **AuraDB Professional** (recommended) - No credit card required, includes Graph Data Science support and Data Importer
** **GraphAcademy Sandbox** (quick start) - Free temporary sandbox provided with this course for learning
** **Self-managed Neo4j** - Neo4j Desktop or Docker installation
* PostgreSQL installed (link:https://postgresapp.com/[Postgres.app^] for macOS or link:https://www.postgresql.org/download/[postgresql.org^])
* Postico (macOS) or pgAdmin (Windows, Linux, macOS) - optional but recommended
* The Northwind database (instructions provided in the course)
Comment on lines +44 to +52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is too much ambiguity here with so many tools, which will lead to confusion. Stick to AuraDB and remove the rest.



=== Duration

{duration}


=== What you will learn

* The fundamental differences between relational and graph data models.
* How to analyze and understand relational database schemas.
* Techniques for mapping relational tables to graph nodes and relationships.
* How to extract data from PostgreSQL databases.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're teaching the concepts of Relational to Graph, not specifically Postgres to Neo4j

* How to use the Neo4j Data Importer to migrate relational data into a Neo4j Aura instance.
* Best practices for validating and querying your imported graph data.


[.includes]
== This course includes

* [lessons]#16 lessons#
* [challenges]#1 hands-on challenge#
* [quizes]#20 quizzes to support your learning#
6,751 changes: 6,751 additions & 0 deletions asciidoc/courses/importing-relational-to-graph/data/northwind.sql

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#4C8EDA', 'primaryTextColor': '#fff', 'primaryBorderColor': '#2563EB', 'lineColor': '#64748B', 'secondaryColor': '#F59E0B', 'tertiaryColor': '#10B981'}}}%%
graph TB
subgraph "Northwind Graph Model - Node Labels"
C((Customer))
O((Order))
P((Product))
Cat((Category))
S((Supplier))
E((Employee))
Sh((Shipper))
end

subgraph "Source Tables"
T1[customers table]
T2[orders table]
T3[products table]
T4[categories table]
T5[suppliers table]
T6[employees table]
T7[shippers table]
end

T1 -->|becomes| C
T2 -->|becomes| O
T3 -->|becomes| P
T4 -->|becomes| Cat
T5 -->|becomes| S
T6 -->|becomes| E
T7 -->|becomes| Sh

style C fill:#4C8EDA,stroke:#2563EB,color:#fff
style O fill:#F59E0B,stroke:#D97706,color:#fff
style P fill:#10B981,stroke:#059669,color:#fff
style Cat fill:#8B5CF6,stroke:#7C3AED,color:#fff
style S fill:#EC4899,stroke:#DB2777,color:#fff
style E fill:#06B6D4,stroke:#0891B2,color:#fff
style Sh fill:#F97316,stroke:#EA580C,color:#fff
Comment on lines +31 to +37
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#4C8EDA', 'primaryTextColor': '#fff', 'lineColor': '#64748B'}}}%%
graph LR
subgraph "Graph Model"
C((Customer))
O((Order))
C -->|PLACED| O
end

subgraph "Relational Model"
CT[customers table<br/>customer_id PK]
OT[orders table<br/>order_id PK<br/>customer_id FK]
CT -.->|referenced by| OT
end

style C fill:#4C8EDA,stroke:#2563EB,color:#fff
style O fill:#F59E0B,stroke:#D97706,color:#fff
style CT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B
style OT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#06B6D4', 'primaryTextColor': '#fff', 'lineColor': '#64748B'}}}%%
graph LR
subgraph "Graph Model"
E((Employee))
O((Order))
E -->|PROCESSED| O
end

subgraph "Relational Model"
ET[employees table<br/>employee_id PK]
OT[orders table<br/>order_id PK<br/>employee_id FK]
ET -.->|referenced by| OT
end

style E fill:#06B6D4,stroke:#0891B2,color:#fff
style O fill:#F59E0B,stroke:#D97706,color:#fff
style ET fill:#E2E8F0,stroke:#94A3B8,color:#1E293B
style OT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#F59E0B', 'primaryTextColor': '#fff', 'lineColor': '#64748B'}}}%%
graph LR
subgraph "Graph Model"
O((Order))
S((Shipper))
O -->|SHIPPED_BY| S
end

subgraph "Relational Model"
OT[orders table<br/>order_id PK<br/>ship_via FK]
ST[shippers table<br/>shipper_id PK]
OT -.->|references| ST
end

style O fill:#F59E0B,stroke:#D97706,color:#fff
style S fill:#F97316,stroke:#EA580C,color:#fff
style OT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B
style ST fill:#E2E8F0,stroke:#94A3B8,color:#1E293B

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#F59E0B', 'primaryTextColor': '#fff', 'lineColor': '#64748B'}}}%%
graph LR
subgraph "Graph Model"
O((Order))
P((Product))
O -->|"CONTAINS<br/>{quantity, unitPrice, discount}"| P
end

subgraph "Relational Model - Junction Table"
OT[orders table<br/>order_id PK]
ODT[order_details table<br/>order_id FK<br/>product_id FK<br/>quantity<br/>unit_price<br/>discount]
PT[products table<br/>product_id PK]
OT -.->|referenced by| ODT
PT -.->|referenced by| ODT
end

style O fill:#F59E0B,stroke:#D97706,color:#fff
style P fill:#10B981,stroke:#059669,color:#fff
style OT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B
style ODT fill:#FEF3C7,stroke:#F59E0B,color:#1E293B
style PT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#10B981', 'primaryTextColor': '#fff', 'lineColor': '#64748B'}}}%%
graph LR
subgraph "Graph Model"
P((Product))
C((Category))
P -->|IN_CATEGORY| C
end

subgraph "Relational Model"
PT[products table<br/>product_id PK<br/>category_id FK]
CT[categories table<br/>category_id PK]
PT -.->|references| CT
end

style P fill:#10B981,stroke:#059669,color:#fff
style C fill:#8B5CF6,stroke:#7C3AED,color:#fff
style PT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B
style CT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#EC4899', 'primaryTextColor': '#fff', 'lineColor': '#64748B'}}}%%
graph LR
subgraph "Graph Model"
S((Supplier))
P((Product))
S -->|SUPPLIES| P
end

subgraph "Relational Model"
ST[suppliers table<br/>supplier_id PK]
PT[products table<br/>product_id PK<br/>supplier_id FK]
ST -.->|referenced by| PT
end

style S fill:#EC4899,stroke:#DB2777,color:#fff
style P fill:#10B981,stroke:#059669,color:#fff
style ST fill:#E2E8F0,stroke:#94A3B8,color:#1E293B
style PT fill:#E2E8F0,stroke:#94A3B8,color:#1E293B

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#06B6D4', 'primaryTextColor': '#fff', 'lineColor': '#64748B'}}}%%
graph TB
subgraph "Graph Model - Employee Hierarchy"
E1((Employee<br/>CEO))
E2((Employee<br/>Manager))
E3((Employee<br/>Staff))
E4((Employee<br/>Staff))

E2 -->|REPORTS_TO| E1
E3 -->|REPORTS_TO| E2
E4 -->|REPORTS_TO| E2
end

subgraph "Relational Model - Self-Reference"
ET[employees table<br/>employee_id PK<br/>reports_to FK → employee_id]
end

style E1 fill:#06B6D4,stroke:#0891B2,color:#fff
style E2 fill:#06B6D4,stroke:#0891B2,color:#fff
style E3 fill:#06B6D4,stroke:#0891B2,color:#fff
style E4 fill:#06B6D4,stroke:#0891B2,color:#fff
style ET fill:#E2E8F0,stroke:#94A3B8,color:#1E293B

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#4C8EDA', 'primaryTextColor': '#fff', 'lineColor': '#64748B', 'fontSize': '14px'}}}%%
graph TB
subgraph "Complete Northwind Graph Model"
C((Customer))
O((Order))
P((Product))
Cat((Category))
S((Supplier))
E((Employee))
Sh((Shipper))

C -->|PLACED| O
E -->|PROCESSED| O
O -->|SHIPPED_BY| Sh
O -->|"CONTAINS<br/>{qty, price, discount}"| P
P -->|IN_CATEGORY| Cat
S -->|SUPPLIES| P
E -->|REPORTS_TO| E
end

style C fill:#4C8EDA,stroke:#2563EB,color:#fff
style O fill:#F59E0B,stroke:#D97706,color:#fff
style P fill:#10B981,stroke:#059669,color:#fff
style Cat fill:#8B5CF6,stroke:#7C3AED,color:#fff
style S fill:#EC4899,stroke:#DB2777,color:#fff
style E fill:#06B6D4,stroke:#0891B2,color:#fff
style Sh fill:#F97316,stroke:#EA580C,color:#fff

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
%%{init: {
'theme': 'base',
'themeVariables': {
'fontFamily': 'system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
'fontSize': '14px'
}
}}%%
flowchart LR
subgraph s1[" "]
A1["<b>1990s</b><br/><br/>1992: Microsoft creates<br/>Northwind as sample<br/>database for Access"]
end

subgraph s2[" "]
A2["<b>2000s</b><br/><br/>Ported to SQL Server<br/>MySQL & PostgreSQL<br/>Standard teaching tool"]
end

subgraph s3[" "]
A3["<b>2010s</b><br/><br/>Countless tutorials<br/>Certification exams<br/>NoSQL migrations"]
end

subgraph s4[" "]
A4["<b>Today</b><br/><br/>Graph migrations<br/>Neo4j resource<br/>Go-to dataset"]
end

s1 ~~~ s2
s2 ~~~ s3
s3 ~~~ s4

style s1 fill:transparent,stroke:transparent
style s2 fill:transparent,stroke:transparent
style s3 fill:transparent,stroke:transparent
style s4 fill:transparent,stroke:transparent

style A1 fill:#3B82F6,stroke:#1D4ED8,stroke-width:1px,color:#FFFFFF
style A2 fill:#10B981,stroke:#059669,stroke-width:1px,color:#FFFFFF
style A3 fill:#8B5CF6,stroke:#7C3AED,stroke-width:1px,color:#FFFFFF
style A4 fill:#F59E0B,stroke:#D97706,stroke-width:1px,color:#FFFFFF
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
%%{init: {
'theme': 'base',
'themeVariables': {
'fontFamily': 'system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
'fontSize': '14px',
'primaryColor': '#DBEAFE',
'primaryBorderColor': '#3B82F6'
}
}}%%
flowchart TB
C["<b>Customers</b><br/>CustomerID | CompanyName | City"]
O["<b>Orders</b><br/>OrderID | CustomerID | OrderDate"]
OD["<b>OrderDetails</b><br/>OrderID | ProductID | Quantity | UnitPrice"]
P["<b>Products</b><br/>ProductID | ProductName | CategoryID"]
Cat["<b>Categories</b><br/>CategoryID | CategoryName"]

C -->|"FK: customer_id"| O
O -->|"FK: order_id"| OD
P -->|"FK: product_id"| OD
P -->|"FK: category_id"| Cat

style C fill:#DBEAFE,stroke:#3B82F6,stroke-width:2px,color:#1E293B
style O fill:#DBEAFE,stroke:#3B82F6,stroke-width:2px,color:#1E293B
style OD fill:#DBEAFE,stroke:#3B82F6,stroke-width:2px,color:#1E293B
style P fill:#DBEAFE,stroke:#3B82F6,stroke-width:2px,color:#1E293B
style Cat fill:#DBEAFE,stroke:#3B82F6,stroke-width:2px,color:#1E293B
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
%%{init: {
'theme': 'base',
'themeVariables': {
'fontFamily': 'system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
'fontSize': '14px'
}
}}%%
flowchart LR
C(("Customer<br/>Alfreds<br/>Berlin"))
O(("Order<br/>2024-01-15"))
P1(("Product<br/>Chai"))
P2(("Product<br/>Chang"))
Cat(("Category<br/>Beverages"))

C -->|PLACED| O
O -->|"CONTAINS<br/>qty: 10"| P1
O -->|"CONTAINS<br/>qty: 5"| P2
P1 -->|IN_CATEGORY| Cat
P2 -->|IN_CATEGORY| Cat

style C fill:#F59E0B,stroke:#D97706,stroke-width:2px,color:#FFFFFF
style O fill:#F59E0B,stroke:#D97706,stroke-width:2px,color:#FFFFFF
style P1 fill:#F59E0B,stroke:#D97706,stroke-width:2px,color:#FFFFFF
style P2 fill:#F59E0B,stroke:#D97706,stroke-width:2px,color:#FFFFFF
style Cat fill:#F59E0B,stroke:#D97706,stroke-width:2px,color:#FFFFFF
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading