Amazon Neptune に loader コマンドで、データのインポートをしてみた

# はじめに

[前回の記事](https://qiita.com/sugimount-a/items/eff6788d646a3cbf8962) では、Amazon Neptune を構築して SPARQL でクエリーをしてみました。今回の記事では、インターネットに公開されている RDF データを Neptune クラスタにインポートする手順を確認していきましょう。

Amazon Neptune には Loader コマンドが用意されており、S3 Bucket に格納されたデータを Neptune にインポートできます。概要図はこんな感じです。

![image-20220305215121065.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/53d044d7-8a4d-3a83-bb72-a346d29ee490.png)

URL : https://docs.aws.amazon.com/ja_jp/neptune/latest/userguide/bulk-load.html



対応しているファイルは、次の4つの形式です。

- N -Triples (`ntriples`) from the specification at https://www.w3.org/TR/n-triples/
- N-Quads (`nquads`) from the specification at https://www.w3.org/TR/n-quads/
- RDF/XML (`rdfxml`) from the specification at https://www.w3.org/TR/rdf-syntax-grammar/
- Turtle (`turtle`) from the specification at https://www.w3.org/TR/turtle/

また、エンコードは UTF8 となっていることが必要です。詳細は次の Document に書かれています。

URL : https://docs.aws.amazon.com/ja_jp/neptune/latest/userguide/bulk-load-tutorial-format-rdf.html



それでは、データのインポートしていきましょう。



# RDF ファイルをダウンロードして S3 に格納

次の URL で公開されている RDF データセットをダウンロードします。

```bash
curl -O http://rdf.geospecies.org/geospecies.rdf.gz
```



S3 Bucket を適当に作成して、ダウンロードしてきたファイルを格納しました。

![image-20220305220405786.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/cb35e89d-04ef-89c7-36cf-128d29e3cf44.png)



# IAM Role の作成

Neptune が S3 にアクセスするための IAM Role を作成していきます。Create Role を押します。

![image-20220305220936289.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/4e8c1584-8be3-a498-2a4d-ddd7cd29ee8c.png)



Custom Trust Policy を選択して、ポリシーに次の文字列を入れます

![image-20220305221226574.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c4d02f62-e635-9571-a925-9bb6740dd025.png)

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "rds.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```



`AmazonS3ReadOnlyAccess` を選択して Next を押します

![image-20220305221335846.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/036abcd2-5df8-0769-b1f8-4bbcc2d0faaf.png)



Role 名などを入力します

![image-20220305221429563.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/63d17a7b-6e84-f373-bb9b-47d301d1ecf7.png)



Create を押します

![image-20220305221442064.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/a3772e58-e8a3-f265-ebcb-b0a406083a34.png)

作成されました

![image-20220305221527194.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/045aab7c-4b53-8d8b-32a6-f15e50a0d71a.png)



# Neptune に IAM Role を紐づける

Neptune  クラスタを選択して、Manage IAM roles を選択します。

![image-20220305230627353.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/164031be-a02e-da3e-96d9-1a27ef986651.png)



作成した IAM Role を選択して、Done を押します。

![image-20220305230656617.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/69aa4948-d38d-b2d5-1b80-27a9d8d2fc35.png)



# S3 Endpoint(Gateway型) を作成

Neptune が S3 にアクセスするために、S3 Endpoint Gateway が必要です。記事の環境では既に設定済みなので、詳細な手順は省略します。

![image-20220305231937758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/c61183f6-c075-301b-6da3-8f9b7ca6651f.png)



設定する内容

- VPC Endpoint の S3 用のものを作成
- Route Table に反映



# Neptune に Loader でインポートする

S3 Bucket にアップロードした RDF データセットを、インポートしていきましょう。Neptune クラスタと同じ VPC に居る EC2 インスタンスで、以下のコマンドを実行します。

```bash
curl -X POST \
    -H 'Content-Type: application/json' \
    https://neptune-test.cluster-chuxmuzmrpgx.ap-northeast-1.neptune.amazonaws.com:8182/loader -d '
    {
      "source" : "s3://neptune-loader-test01/geospecies.rdf.gz", 
      "format" : "rdfxml",
      "iamRoleArn" : "arn:aws:iam::xxxxxxxxxxxx:role/Neptune-S3-Role",
      "region" : "ap-northeast-1",
      "failOnError" : "FALSE",
      "parallelism" : "HIGH"
    }'
```



実行例

- Status : 200 がレスポンスとして帰ってくる

```json
{
    "status" : "200 OK",
    "payload" : {
        "loadId" : "2943d79e-dfba-4aa4-8ab7-4c2e21029234"
    }
}
```



進行状況の確認

```bash
curl -G 'https://neptune-test.cluster-chuxmuzmrpgx.ap-northeast-1.neptune.amazonaws.com:8182/loader/2943d79e-dfba-4aa4-8ab7-4c2e21029234'
```



実行例 : ロード中の状態です。status が `LOAD_IN_PROGRESS`となっています

```json
{
    "status" : "200 OK",
    "payload" : {
        "feedCount" : [
            {
                "LOAD_IN_PROGRESS" : 1
            }
        ],
        "overallStatus" : {
            "fullUri" : "s3://neptune-loader-test01/geospecies.rdf.gz",
            "runNumber" : 1,
            "retryNumber" : 0,
            "status" : "LOAD_IN_PROGRESS",
            "totalTimeSpent" : 130,
            "startTime" : 1646489330,
            "totalRecords" : 1350000,
            "totalDuplicates" : 0,
            "parsingErrors" : 0,
            "datatypeMismatchErrors" : 0,
            "insertErrors" : 0
        }
    }
}
```



ロード完了の状態です。status が `LOAD_COMPLETED` となっています

```json
{
    "status" : "200 OK",
    "payload" : {
        "feedCount" : [
            {
                "LOAD_COMPLETED" : 1
            }
        ],
        "overallStatus" : {
            "fullUri" : "s3://neptune-loader-test01/geospecies.rdf.gz",
            "runNumber" : 1,
            "retryNumber" : 0,
            "status" : "LOAD_COMPLETED",
            "totalTimeSpent" : 199,
            "startTime" : 1646489330,
            "totalRecords" : 2201532,
            "totalDuplicates" : 0,
            "parsingErrors" : 0,
            "datatypeMismatchErrors" : 0,
            "insertErrors" : 0
        }
    }
}
```



# Neptune Workbench でクエリー確認

前回の手順で作成した Jupyter Notebook にある Neptune Workbench で SPARQL クエリーでインポートしたデータを確認しましょう。

以下のコマンドを実行して、すべてのデータの中から 10 件取得します。 

```
%%sparql

SELECT ?s ?p ?o WHERE {?s ?p ?o} LIMIT 10
```

![image-20220305232154563.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/34a656e4-2e8f-6750-fba9-fbcadf33226a.png)



次に以下のクエリーを実行します。(このクエリーの意味が何を指しているのか、調べきれませんでした・・・すいません、時間があれば調べたいと思います)

```
%%sparql

PREFIX geospecies: <http://rdf.geospecies.org/ont/geospecies#>
SELECT DISTINCT ?kingdom ?commonName WHERE{

  ?node geospecies:hasKingdomName ?kingdom;
  a geospecies:KingdomConcept;
  geospecies:hasCommonName ?commonName .

}
```

![image-20220305233325912.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/deabe07d-457b-71c0-99d3-3bfc8bd8f9ab.png)



同様に次のクエリーを実行します

```
%%sparql

PREFIX geospecies: <http://rdf.geospecies.org/ont/geospecies#>
SELECT DISTINCT ?commonName WHERE{

  ?node geospecies:hasFamilyName ?familyName;
  geospecies:hasCommonName ?commonName;
  FILTER regex(?familyName, "Strigidae") .    
} LIMIT 10
```

![image-20220305233339935.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/75ad2d44-9da0-edf8-2c81-773e751e0d99.png)



# 参考URL

https://zatoima.github.io/aws-neptune-create-instance-execute-query-try.html

https://www.agilevision.io/blog/store-and-access-graph-data-using-aws-neptune-part-1