> For the complete documentation index, see [llms.txt](https://csse-uwa.gitbook.io/data-warehousing-lab-sheets/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://csse-uwa.gitbook.io/data-warehousing-lab-sheets/week-9-import-data-from-a-relational-database-into-neo4j.md).

# Week 9 - Import data from a relational database into Neo4j

In this lab, we'll learn how to import data from a relational database into Neo4j. By the end of this session, you should be able to design and create your graph for Project 2.

## 1. Dataset

{% file src="/files/f1g6eZ2sshM2SxxwJlvU" %}
Week 9 Lab Dataset (3 CSV files)
{% endfile %}

It is a star schema of a sales warehouse with one fact table and two dimension tables:

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2Fn6QFVtX1yimprPbKih4a%2Fimage.png?alt=media&amp;token=b2848f84-075f-41ca-81b0-dfe8a505c8ef" alt=""><figcaption><p>Star Schema</p></figcaption></figure>

## 2. Design and ETL

### 2.1 Graph Database Design

**Step 1:** Design a graph database schema using the [Arrows Tool](https://arrows.app/) that reflects the warehouse's star schema. Think about the general principles that&#x20;

* A row is a node
* A table name is a label name
* A join table or foreign key is a relationship

Your schema might look like this:

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F8Tg4FU3GjuceSoNk7lji%2Fimage.png?alt=media&amp;token=dbc2475c-6875-47a2-b738-73302876a028" alt=""><figcaption></figcaption></figure>

Relationship labels and property names are self-designed based on the data. Feel free to use different names.

### **2.2**. Prepare CSV Files Nodes

Let's implement it in a Python dataframe.

<pre class="language-python"><code class="lang-python">import pandas as pd
# load CSV files into pandas DataFrames. 
# Remember to change the data path
sales_table = pd.read_csv('./data/sales.csv')
products_table = pd.read_csv('./data/products.csv')
shops_table = pd.read_csv('./data/shops.csv')

# use ".head()" to review your tables
<strong># sales_table.head()
</strong># products_table.head()
# shops_table.head()
</code></pre>

After comparing the graph schema (Figure 1) with the data, we can find that "shop" nodes come from the "shops\_table" and "product" nodes come from the "products\_table". However, the "sale" nodes require some ETL processing:

```python
# Keeping only specified columns using loc method
sales_node_table = sales_table.loc[:, ['Sale ID', 'Date', 'Quantity', 'Unit price']]
# export to csv
sales_node_table.to_csv('./data/sales_node.csv', index=False)
```

Now, we have all CSV files for nodes. Let's import them into Neo4j.

### **2.3.** Import CSV Files

The screenshots below are from Neo4j Desktop. If you're using the cloud version, the steps are similar.

{% hint style="info" %}
We assume you have created an instance and a database for this lab; if you haven't, please refer to the Week 8 lab to create them.
{% endhint %}

#### **2.3.1.** Import CSV Files

Click the folder icon to open the directory.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FFTcRxhRUgqkU7IfnVvUg%2Fimage.png?alt=media&amp;token=654faacb-eec4-459b-9db2-a33cd7eec7ac" alt=""><figcaption></figcaption></figure>

Move CSV files lto the "**import"** directory. (Note: if the "import" directory doesn't exist, you can create it yourself.)

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FiFm5jY7zpNgFYtnnNnsC%2Fimage.png?alt=media&amp;token=8ebc76db-1814-4b85-b00a-a4605c1df7a9" alt=""><figcaption></figcaption></figure>

#### **2.3.2.** Create Nodes

Let's start by creating "Shop" nodes. Under the "Query" sub-menu, write the code below and click the "run" button on the right. The variable name "row" represents each row in the imported CSV file, in this case, "shops.csv". You can rename "row" to another variable name if you prefer. Use "row\.HEADER\_NAME" to refer to each header. For instance, row: "Shop ID" refers to the "Shop ID" column in "shops.csv". <mark style="color:red;">**The HEADER\_NAME must exactly match the CSV header, including case sensitivity.**</mark> The properties before the ":" are the ones you've named in your schema design (Figure 1).

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FQ5OeAr94I44FDuyBYi5o%2Fimage.png?alt=media&amp;token=5d90bdc6-ff30-48af-9951-90917dcc9308" alt=""><figcaption></figcaption></figure>

```cypher
LOAD CSV WITH HEADERS FROM 'file:///shops.csv' AS row
CREATE (d:Shop {
    shopID: row.`Shop ID`,
    city: row.City,
    stateOrRegion: row.`State or region`,
    country: row.Country,
    shopSize: row.`Shop size`
})
```

You have 2 ways to check nodes you created.

* Solution 1: Under the "query" menu, click "Database overview"

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2Fl0JREirv5qQfTZJ1CcZE%2Fimage.png?alt=media&amp;token=5b7487a4-908f-42a2-8f03-c5fd4a1d08c9" alt=""><figcaption></figcaption></figure>

You can click the "shop" bubble to check nodes.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FYSYTR6TCJQFfIlYT0Ns2%2Fimage.png?alt=media&amp;token=b8a299da-ee8f-4c41-af96-98b72d80805f" alt=""><figcaption></figcaption></figure>

There are 3 different views: Graph, Table and Raw.

* Solution 2: Click "Explore", then click "Show me a graph".

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FvueqdH6MOGebAB3lu8kZ%2Fimage.png?alt=media&amp;token=ce4297c1-a31c-456f-be81-28750e34129d" alt=""><figcaption></figcaption></figure>

But only one node is showing in this solution.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FgCOw2GwyfgIpTcjNFPRp%2Fimage.png?alt=media&amp;token=5eb68c3a-e185-4e25-b10c-7be29df27d0d" alt=""><figcaption></figcaption></figure>

Follow a similar process for creating "Product" and "Sale" nodes:

```cypher
LOAD CSV WITH HEADERS FROM 'file:///products.csv' AS row
CREATE (d:Product {
    productID: row.`Product`,
    category: row.Category,
    subcategory: row.`Sub category`,
    productSize: row.Size,
    purchasePrice: row.`Purchase price`,
    color: row.Color,
    brand:row.Brand
})
```

```cypher
LOAD CSV WITH HEADERS FROM 'file:///sales_node.csv' AS row
CREATE (d:Sale {
    saleID: row.`Sale ID`,
    date: row.Date,
    quantity: row.Quantity,
    unitPrice:row.`Unit price`
})
```

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FZsy6xnDcCkx9KT2Jvoj7%2Fimage.png?alt=media&amp;token=3917306f-6428-405c-a5fd-4234251b3f7d" alt=""><figcaption></figcaption></figure>

**Your turn: Assign different colours to each label. You can refer to the Week 8 lab sheet for guidance. For example:**<br>

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F8DSrog1KjQOrfVCjjXa8%2Fimage.png?alt=media&amp;token=9b9f82de-9fcd-4d1a-9b9a-6ca44d4d7ac3" alt=""><figcaption></figcaption></figure>

### **2.4**. Prepare CSV files for Relationships

#### **2.4.1.** Create Relationships

Based on the graph schema (Figure 1), we would like to create the relationship "CONTAINS" from "Sale" to "Product", "SOLD\_IN" from "Sale" to "Shop":

```python
# as you can see, the relationship between "Sale" and "Product" can obtain from "sales_table"
contain_table = sales_table.loc[:, ['Sale ID', 'Product']]
contain_table.to_csv('./data/rel_contains.csv', index=False)
```

```python
# as you can see, the relationship between "Sale" and "Shop" can also obtain from "sales_table"
sold_in_table = sales_table.loc[:, ['Sale ID', 'Shop']]
sold_in_table.to_csv('./data/rel_sold_in.csv', index=False)
```

#### **2.4.2.** Import CSV Files and Create Relationships

Copy "rel\_sold\_in.csv" and "rel\_contains.csv" into the "import" folder and run the following code. "->" indicates the direction of the relationship. If you want to create an undirected relationship, use `CREATE (s)-[:CONTAINS]-(p)`.

```cypher
LOAD CSV WITH HEADERS FROM 'file:///rel_contains.csv' AS row
MATCH (s:Sale {saleID: row.`Sale ID`}),
(p:Product { productID: row.Product})
CREATE (s)-[:CONTAINS]->(p)
```

```cypher
LOAD CSV WITH HEADERS FROM 'file:///rel_sold_in.csv' AS row
MATCH (s:Sale {saleID: row.`Sale ID`})
MATCH(p:Shop { shopID: row.Shop})
CREATE (s)-[:SOLD_IN]->(p)
```

{% hint style="info" %}
When running the two queries above, why does the first query produce a warning but the second one runs without any warning?
{% endhint %}

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F3wNt9hSG7gYyKj1NHE0m%2Fimage.png?alt=media&amp;token=02dfe493-5d25-4a7b-b47a-db4faea08c0e" alt=""><figcaption></figcaption></figure>

Now that you've created your graph database from a relation database, <mark style="color:red;">**you might wonder if you can have additional node labels**</mark>. For instance, separating "country" from "shop" or "category" and "subcategory" from "product". The answer is "Yes". There's no fixed answer in design; it depends on how you intend to use your graph.

Refer to the week 8 lab sheet, can you

* Show nodes only
* Show nodes with relationships
* Delete relationships first, then delete all nodes
* Delete all nodes and relationships together.

### 2.5 Create nodes and relationships using the GUI

{% hint style="warning" %}
Note that this method is not permitted in Project 2. Marks will be awarded for the Cypher queries used to create nodes and relationships.
{% endhint %}

#### 2.5.1 Import CSV files

Under the "Import", you can import all CSV files.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FGFlM5VxLvkqJzsxJylWO%2Fimage.png?alt=media&amp;token=380aa6d5-539c-41c4-ae52-e4f6776c542e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2Fjs07DJ9w9X0vczTht3xz%2Fimage.png?alt=media&amp;token=a61b7e5f-ca1e-40ea-8c28-88e3151aa190" alt=""><figcaption></figcaption></figure>

#### 2.5.2 Start sketching a model

Click "Add node label". A new interface like Arrow\.app will display.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2Ff1O14AisogS3YqhAMqss%2Fimage.png?alt=media&amp;token=5862b1ed-c0fb-4265-8d9a-841fe84a4b7d" alt=""><figcaption></figcaption></figure>

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2Fbbf84idH9eOy8MvuTD7K%2Fimage.png?alt=media&amp;token=528bcd52-f075-4cd7-a5ba-90e78ba35501" alt=""><figcaption></figcaption></figure>

#### 2.5.3 Setup nodes

Type a label name, select a file, set up properties and ID.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FG26nXVhsRlbWScYK9k4L%2Fimage.png?alt=media&amp;token=09dbf08c-88cc-4108-a246-ee9cd6b6a93f" alt=""><figcaption></figcaption></figure>

You have two methods to set up properties:

* Map from file

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FlrJomkPBi1zDtcVrKRkP%2Fimage.png?alt=media&amp;token=c3d6022d-86ab-440a-9acd-46f47362c0ba" alt=""><figcaption></figcaption></figure>

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FdDyKYll41Dqb0FJpSCUl%2Fimage.png?alt=media&amp;token=e83d5815-92a8-4261-a26f-f3d188f09132" alt=""><figcaption></figcaption></figure>

* Manually set up. Click the "+" icon, manually type the property names, data types and select columns.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FF7XWvy0P1QxAiSI570bj%2Fimage.png?alt=media&amp;token=1fb32982-44f2-4722-9170-c0d9289b5fd3" alt=""><figcaption></figcaption></figure>

#### 2.5.4 Delete property

If a property needs to be deleted, select the property name, click delete.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F7qvhqBPKfQKNjzoPG1M9%2Fimage.png?alt=media&amp;token=aa695b9b-744a-4988-a8bd-e7f6d5e3204e" alt=""><figcaption></figcaption></figure>

#### 2.5.5 Create a relationship

You can create nodes and relationships in the interface the same way you do in Arrow\.app.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F1RlKZjk53dKg8WQPuyiQ%2Fimage.png?alt=media&amp;token=99a93cbb-873d-4226-be9d-16787e4cf8f9" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Set up the sales node by yourself.
{% endhint %}

#### 2.5.6 Setup relationships

In the graph, the direction should be from sales to product; we can reverse the direction by clicking "Reverse direction".

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FWacni5WvlWwhDrctXibT%2Fimage.png?alt=media&amp;token=4f54440a-5f21-4847-a069-7ac3f58398c9" alt=""><figcaption></figcaption></figure>

Type the relationship label, select the CSV file and map the nodes.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F7NqCLE1gSP0yrFMBGeYV%2Fimage.png?alt=media&amp;token=46e95a38-203a-4ca4-934d-eecbb5748f44" alt=""><figcaption></figcaption></figure>

#### 2.5.7 Run import

Click "Run import" to import nodes and relationships.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F9iX8dH5NQxCOA0czadNM%2Fimage.png?alt=media&amp;token=5a84c55c-abef-4ae4-a96f-098c23c50373" alt=""><figcaption></figcaption></figure>

You should see the results, and you can explore the results.

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2F31B1hwl3a9B55bYI6M9z%2Fimage.png?alt=media&amp;token=bf52b7f3-b8ee-4145-b29e-43b0f1e487ae" alt=""><figcaption></figcaption></figure>

<figure><img src="https://374096590-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FE6tM8okJTaOtct7O9mvr%2Fuploads%2FXS06RFgF9uxakpzhxNTa%2Fimage.png?alt=media&amp;token=4072b2f9-ece6-4130-b203-37b0ac6f4d27" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Your turn:

Create the shop nodes and the relationship between the shop and sales.
{% endhint %}

Next week, we'll explore querying graph databases using Cypher.
