Amazon Web Services ブログ

Amazon NeptuneとAWS Amplifyを利用したグラフアプリケーション開発

グラフデータベースの活用が様々な領域で進んでいます。例えば、公共領域では 法人情報検索ツール、ヘルスケア領域では薬物間相互作用のチェック、マーケティング領域ではカスタマーインサイト分析などで利用されています。
リレーションシップと大量に接続されたデータセットと連携するアプリケーション開発において、リレーショナルデータベースで実装するのは困難です。しかし、フルマネージドなグラフデータベースである Amazon Neptuneはリレーションシップの格納とナビゲートを目的として構築されたデータベースで、 ナレッジグラフIDグラフ不正検出といった代表的なグラフアプリケーションを構築することができます。最近では、ナレッジグラフを利用したチャットボットアプリケーションのサンプルを AWS CloudFormation templateとしてリリースしました。
AWS Amplifyはウェブアプリケーション開発するデベロッパー向けのサービスで、グラフアプリケーションの機能をウェブアプリケーションに容易に組み込むことができます。 AWS AppSync はGraphQL APIを簡単に実装することが可能で、例えば、データへのアクセスレイヤーを提供し、 AWS Lambdaを利用してNeptuneに接続するフレキシブルなバックエンド実装が可能です。
本ブログでは、AWS Amplifyで作成したアプリケーションからNeptuneの接続する方法をご紹介します。

ソリューション概要

ソリューションのアーキテクチャ図は以下です。

本ソリューションはAmplifyを利用してアプリケーションをホスティングし、Amazon Neptuneへのアクセスは全てAWS AppSync経由でAWS Lambdaを呼び出して処理します。フロントエンドにはReact、バックエンドの Lambda は Node.js を利用しています。アプリケーションは、 Apache TinkerPop Gremlin を利用してNeptuneのグラフデータへアクセスしています。

本ソリューションを利用すると以下のデモ画面のUIが実装でき、操作することができます。

 

ナビゲーションペインには、以下の機能を実装しています:

  • Dashboard – person name, product name, or affiliated academic societyを入力することで、入力情報に関連のある情報を取得できます。
  • Amazon Neptune AWSマネージメントコンソールのAmazon Neptuneへ画面遷移します。
  • Amazon SageMaker – AWSマネージメントコンソールのAmazon SageMakerへ画面遷移します。
  • Add Vertex/Edge – ノードとエッジをAmazon Neptuneに追加することができます。
  • Visualizing Graph – Amazon Neptuneに登録したグラフデータをビジュアライズ化します。グラフデータのノードを選択すると、プロパティ情報を表示できます。

本ソリューションで利用するノードとエッジのグラフスキーマは下表の通りです。

Vertex Description
person Doctor or MR
paper Paper authored by person
product Medicine used by person
conference Affiliated academic society
institution Hospital, university, or company
Edge Source Target
knows person person
affiliated_with person institution
authored_by paper person
belong_to person conference
made_by product institution
usage person product

前提条件

本ソリューション利用には、以下が必要です。

  • AWSアカウント – 作成されていない方は、こちらからアカウントを作成してください。
  • AWS Region – 本ソリューションでus-east-1を利用します。
  • バルクロード用のIAMロールとAmazon S3権限の設定 – Amazon Neptuneへのデータロードはバルクロード機能を利用します。AWS Identity and Access Management (IAM) ロールと Amazon Simple Storage Service (Amazon S3) VPC Endpointが必要です。 こちらのIAMロールとAmazon S3 VPC Endpoint を作成してください。詳細については、 Prerequisites: IAM Role and Amazon S3 Accessを参照してください。なお、作成したロールのAmazon Neptune への紐付けは 次のステップで行います。

AWS Cloud9環境の作成

まず、AWS Cloud9環境の作成から行います。

  1. AWS Cloud9コンソールにて, 以下のパラメータで環境を構築します:
    1. Instance type – m5.large
    2. Network (VPC)us-east-1
    3. Subnetus-east-1a
  2. 次に、以下のスクリプトをresize.shとして保存します。これは、AWS Cloud9 にアタッチされている Amazon Elastic Block Store (Amazon EBS) のVolumeサイズを変更するために利用します。
    #!/bin/bash
    
    # Specify the desired volume size in GiB as a command-line argument. If not specified, default to 20 GiB.
    SIZE=${1:-20}
    
    # Get the ID of the environment host Amazon EC2 instance.
    INSTANCEID=$(curl http://169.254.169.254/latest/meta-data/instance-id)
    
    # Get the ID of the Amazon EBS volume associated with the instance.
    VOLUMEID=$(aws ec2 describe-instances \
    --instance-id $INSTANCEID \
    --query "Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId" \
    --output text)
    
    # Resize the EBS volume.
    aws ec2 modify-volume --volume-id $VOLUMEID --size $SIZE
    
    # Wait for the resize to finish.
    while [ \
    "$(aws ec2 describe-volumes-modifications \
    --volume-id $VOLUMEID \
    --filters Name=modification-state,Values="optimizing","completed" \
    --query "length(VolumesModifications)" \
    --output text)" != "1" ]; do
    sleep 1
    done
    
    # Check if we're on an NVMe filesystem
    if [ $(readlink -f /dev/xvda) = "/dev/xvda" ]
    then
    # Rewrite the partition table so that the partition takes up all the space that it can.
    sudo growpart /dev/xvda 1
    
    # Expand the size of the file system.
    # Check if we are on AL2
    STR=$(cat /etc/os-release)
    SUB="VERSION_ID=\"2\""
    if [[ "$STR" == *"$SUB"* ]]
    then
    sudo xfs_growfs -d /
    else
    sudo resize2fs /dev/xvda1
    fi
    
    else
    # Rewrite the partition table so that the partition takes up all the space that it can.
    sudo growpart /dev/nvme0n1 1
    
    # Expand the size of the file system.
    # Check if we're on AL2
    STR=$(cat /etc/os-release)
    SUB="VERSION_ID=\"2\""
    if [[ "$STR" == *"$SUB"* ]]
    then
    sudo xfs_growfs -d /
    else
    sudo resize2fs /dev/nvme0n1p1
    fi
    fi

    実行するスクリプトの詳細は、Moving an environment and resizing or encrypting Amazon EBS volumesを参照してください。

  3. Volumeサイズを20GBとするため以下を実行してください。
    $ touch resize.sh
    $ bash resize.sh 20
    $ df –h
    Filesystem Size Used Avail Use% Mounted on
    devtmpfs 3.8G 0 3.8G 0% /dev
    tmpfs 3.8G 0 3.8G 0% /dev/shm
    tmpfs 3.8G 440K 3.8G 1% /run
    tmpfs 3.8G 0 3.8G 0% /sys/fs/cgroup
    /dev/nvme0n1p1 20G 8.5G 12G 43% /
    tmpfs 777M 0 777M 0% /run/user/1000

Neptuneリソースの作成

AWS Command Line Interface (以下、AWS CLI)を利用してAmazon Neptuneを作成します。

  1. 以下のコマンドを実行し、Neptune DB clusterとinstanceを作成します。
    $ aws neptune create-db-cluster --db-cluster-identifier ws-database-1 --engine neptune --engine-version 1.0.4.1
    $ aws neptune create-db-instance --db-instance-identifier ws-neptune --db-instance-class db.r5.xlarge --engine neptune --db-cluster-identifier ws-database-1
    $ aws neptune create-db-instance --db-instance-identifier ws-read-neptune --db-instance-class db.r5.xlarge --engine neptune --db-cluster-identifier ws-database-1 
  2. 前提条件で作成したIAMロールをAmazon Neptuneにアタッチしてください。
  3. セキュリティグループのインバウンドルールに以下のルールを追加し、Amazon Neptuneクラスターにアタッチしてください。これは、次のステップでAWS Cloud9からAmazon Neptuneにバルクロードのコマンドを実行するために必要です。
    1. Type – Custom TCP
    2. Port range – 8182
    3. Source – Custom, with the security group of the AWS Cloud9 instance

S3バケットの作成 とNeptuneへのバルクロード

このステップではS3バケットを作成して、グラフデータをアップロードします。

  1. us-east-1にS3バケットを作成して、以下のファイルをアップロードしてください。今回はGremlinを利用するため、Gremlinロードデータ形式にしています。今回利用するノードのサンプルデータ (vertex.csv)は次の通りです
    ~id, name:String, speciality:String, publish_date:String, ~label
    Doctor1,"John","psychosomatic medicine", ,person
    Doctor2,"Bob","respiratory medicine", ,person
    Doctor3,"Alice","gastroenterology", ,person
    Doctor4,"Terry","neurology", ,person
    Doctor5,"Ken","cardiology", ,person
    Doctor6,"Peter","neurology", ,person
    MR1,"Mashiko", , ,person
    MR2,"Koizumi", , ,person
    MR3,"Ishio", , ,person
    Paper1,"Example1", ,"2000-05-13",paper
    Paper2,"Example2", ,"2005-01-20",paper
    Paper3,"Example3", ,"2010-06-20",paper
    Paper4,"Example4", ,"2018-11-13",paper
    Paper5,"Example5", ,"2020-08-13",paper
    Prod1,"A medicine", , ,product
    Prod2,"B medicine", , ,product
    Prod3,"C medicine", , ,product
    Prod4,"D medicine", , ,product
    Prod5,"E medicine", , ,product
    Conf1,"X conference", , ,conference
    Conf2,"Y conference", , ,conference
    Conf3,"Z conference", , ,conference
    Inst1,"A hospital", , ,institution
    Inst2,"B hospital", , ,institution
    Inst3,"C Univ", , ,institution
    Inst4,"A pharma", , ,institution
    Inst5,"B pharma", , ,institution

    エッジのサンプルデータ (edge.csv)は以下です。

    ~id, ~from, ~to, ~label, weight:Double
    e1,Doctor1,Doctor2,knows,
    e2,Doctor2,Doctor4,knows,
    e3,MR1,Doctor2,knows,
    e4,MR1,Doctor1,knows,
    e5,MR2,MR1,knows,
    e6,MR1,MR2,knows,
    e7,MR3,MR1,knows,
    e8,Doctor3,Doctor1,knows,
    e9,Doctor4,Doctor5,knows,
    e10,Doctor4,Doctor6,knows,
    e11,Doctor3,Doctor4,knows,
    e12,Doctor5,Doctor6,knows,
    e13,Doctor5,Doctor3,knows,
    e14,Doctor6,Doctor5,knows,
    e15,Doctor6,Doctor2,knows,
    e16,Doctor2,Doctor5,knows,
    e17,Doctor5,Doctor2,knows,
    e18,Doctor6,Doctor3,knows,
    e19,Doctor3,Doctor6,knows,
    e20,MR2,Doctor3,knows,
    e21,MR2,Doctor6,knows,
    e22,MR1,Inst4,affiliated_with,
    e23,MR2,Inst4,affiliated_with,
    e24,MR3,Inst5,affiliated_with,
    e25,Doctor1,Inst1,affiliated_with,
    e26,Doctor2,Inst1,affiliated_with,
    e27,Doctor3,Inst2,affiliated_with,
    e28,Doctor4,Inst2,affiliated_with,
    e29,Doctor5,Inst3,affiliated_with,
    e30,Doctor6,Inst3,affiliated_with,
    e31,Paper1,Doctor1,authored_by,
    e32,Paper1,Doctor3,authored_by,
    e33,Paper2,Doctor2,authored_by,
    e34,Paper2,Doctor5,authored_by,
    e35,Paper3,Doctor3,authored_by,
    e36,Paper3,Doctor6,authored_by,
    e37,Paper4,Doctor1,authored_by,
    e38,Paper5,Doctor5,authored_by,
    e39,Paper5,Doctor6,authored_by,
    e40,Doctor1,Conf1,belong_to,
    e41,Doctor2,Conf1,belong_to,
    e42,Doctor3,Conf2,belong_to,
    e43,Doctor3,Conf3,belong_to,
    e44,Doctor4,Conf2,belong_to,
    e45,Doctor5,Conf2,belong_to,
    e46,Doctor5,Conf3,belong_to,
    e47,Doctor6,Conf1,belong_to,
    e48,Prod1,Inst4,made_by,
    e49,Prod2,Inst5,made_by,
    e50,Prod3,Inst4,made_by,
    e51,Prod4,Inst5,made_by,
    e52,Prod5,Inst4,made_by,
    e53,Doctor1,Prod1,usage,1.0
    e54,Doctor1,Prod2,usage,0.5
    e55,Doctor1,Prod3,usage,0.2
    e56,Doctor2,Prod1,usage,0.5
    e57,Doctor2,Prod3,usage,0.5
    e58,Doctor3,Prod4,usage,0.9
    e59,Doctor3,Prod5,usage,0.2
    e60,Doctor4,Prod4,usage,0.6
    e61,Doctor5,Prod5,usage,0.9
    e62,Doctor5,Prod4,usage,0.2
    e63,Doctor5,Prod3,usage,0.4
    e64,Doctor5,Prod2,usage,0.3
    e65,Doctor6,Prod1,usage,1.0
  2. AWS Cloud9から以下のコマンドを実行して、Amazon Neptuneにノードデータをロードします。
    $ curl -X POST \
    -H 'Content-Type: application/json' \
    https://Your-Amazon-Neptune-Writer-Endpoint-Name:8182/loader -d '
    {
    "source" : "s3://Your-Bucket-name/vertex.csv",
    "format" : "csv",
    "iamRoleArn" : "IAM-Role-Arn-you-made",
    "region" : "us-east-1",
    "failOnError" : "FALSE",
    "parallelism" : "MEDIUM",
    "updateSingleCardinalityProperties" : "FALSE",
    "queueRequest" : "TRUE"
    }
    '
    #Response
    {
    "status" : "200 OK",
    "payload" : {
    "loadId" : "xxxxxxxxxxxxxxxxx"
    }
  3. 以下のコマンドを実行し、バルクロードが成功したか(LOAD_COMPLETED)を確認します。
    $ curl -G 'https://Your-Amazon-Neptune-Reader-Endpoint-Name:8182/loader/xxxxxxxxxxxxxxxxx'
    
    #Response
    {
    "status" : "200 OK",
    "payload" : {
    "feedCount" : [
    {
    "LOAD_COMPLETED" : 1
    }
    ],
    "overallStatus" : {
    "fullUri" : "s3://Your-Bucket-name/vertex.csv",
    "runNumber" : 1,
    "retryNumber" : 0,
    "status" : "LOAD_COMPLETED",
    "totalTimeSpent" : 3,
    "startTime" : 1612877196,
    "totalRecords" : 78,
    "totalDuplicates" : 0,
    "parsingErrors" : 0,
    "datatypeMismatchErrors" : 0,
    "insertErrors" : 0
    }
    }
  4. 同様にして、 sourceedge.csv が格納されているS3 URIに変更して、エッジデータをバルクロードします。

これでNeptuneへのグラフデータの登録は完了です。

Amplifyでのグラフアプリケーション構築

ここからは、AWS Amplifyを利用してNeptuneにアクセスするアプリケーションを実装します。AWS Cloud9でAmplifyの設定を行い、ユーザー認証、Neptuneを操作するバックエンドのLambda functionやGraphQL APIなどのコンポーネントを追加していきます。

Amplifyの設定

先ほどのステップで作成したAWS Cloud9環境のターミナルからAmplifyの設定を行います。

  1. WebブラウザにてCloud9環境を開き、次のコマンドを実行してください。$ amplify configure を実行すると、ユーザーに代わってAmplifyがアプリケーションをデプロイできるように、新しいIAMユーザーが作成されます。設定内容はdefault というプロファイル名で保存します。設定の詳細は、Configure the Amplify CLIを参照してください。
    $ npm install -g @aws-amplify/cli@latest # install Amplify CLI
    $ amplify configure # initial configuration of Amplify
    Initializing new Amplify CLI version...
    Done initializing new version.
    Scanning for plugins...
    Plugin scan successful
    Follow these steps to set up access to your AWS account:
    Sign in to your AWS administrator account:
    https://console.thinkwithwp.com/
    Press Enter to continue
    Specify the AWS Region
    ? region: us-east-1
    Specify the username of the new IAM user:
    ? user name: amplify-user
    Complete the user creation using the AWS console
    https://console.thinkwithwp.com/iam/home?region=us-east-1#/users$new?step=final&accessKey&userNames=amplify-user&permissionType=policies&policies=arn:aws:iam::aws:policy%2FAdministratorAccess
    Press Enter to continue
    Enter the access key of the newly created user:
    ? accessKeyId: ********************
    ? secretAccessKey: ****************************************
    This would update/create the AWS Profile in your local machine
    ? Profile Name: default
    Successfully set up the new user.
  2. 次のコマンドでReact アプリケーションのテンプレートを作成します。create-react-appコマンドでReact アプリケーションのテンプレートを作成します。テンプレートが作成されると、react-amplify-neptune-workshop というディレクトリが作成されるので、当該ディレクトリに移動して Amplify の設定を行います。
    $ npx create-react-app react-amplify-neptune-workshop
    $ cd react-amplify-neptune-workshop
    $ npm install aws-amplify @aws-amplify/ui-react @material-ui/core @material-ui/icons clsx react-router-dom react-vis-force
  3. 同ディレクトリ (react-amplify-neptune-workshop)で$ amplify initを実行し、先ほど作成した default プロファイルを使って Amplify アプリケーションをイニシャライズします。
    $ amplify init
    Note: It is recommended to run this command from the root of your app directory
    ? Enter a name for the project neptune
    ? Enter a name for the environment dev
    ? Choose your default editor: None
    ? Choose the type of app that you're building javascript
    Please tell us about your project
    ? What javascript framework are you using react
    ? Source Directory Path: src
    ? Distribution Directory Path: build
    ? Build Command: npm run-script build
    ? Start Command: npm run-script start
    Using default provider awscloudformation
    
    For more information on AWS Profiles, see:
    https://docs.thinkwithwp.com/cli/latest/userguide/cli-configure-profiles.html
    
    ? Do you want to use an AWS profile? Yes
    ? Please choose the profile you want to use default

    AmplifyがAWS CloudFormationを利用してアプリケーションのバックエンドを自動的に構築します。これは数分で完了します。

  4. AWS Cloud9 のターミナルをもう一つ開き、以下のコマンドを実行します。
    $ cd react-amplify-neptune-workshop
    $ npm start
  5. AWS Cloud9 のMenu barにある Preview をクリックし、Preview Running Application を選択します。React アプリケーションが Cloud9 の画面右半分に表示され、アプリケーションコードの変更がすぐにプレビューで確認できます。

Authentication

次に、以下のコマンドを実行してアプリケーションに認証の機能を追加します。コマンドを実行すると、AmplifyはAWS CloudFormationを用いて認証バックエンドの Amazon Cognitoユーザープールを作成します。次の例のように対話形式で質問に答えることで、ユーザ名とパスワードでログインできる設定を行います。

$ amplify add auth 
Using service: Cognito, provided by: awscloudformation

The current configured provider is Amazon Cognito. 

Do you want to use the default authentication and security configuration? Default configuration
Warning: you will not be able to edit these selections. 
How do you want users to be able to sign in? Username
Do you want to configure advanced settings? No, I am done.
Successfully added auth resource neptuneff8d594a locally

認証のフロントエンドを作成します。次のコマンドを実行して、フロントエンドのコードをダウンロードし、既存のコードと置き換えます。認証画面はCloud9でアプリケーションのプレビューで確認できます。

以下のコマンドでApp.js ファイルを置き換えます。これで、認証のフロントエンドが作成できました。

$ wget https://aws-database-blog.s3.amazonaws.com/artifacts/DBBLOG-1462/App.js -O ~/environment/react-amplify-neptune-workshop/src/App.js

この後のステップでcomponentsディレクトリを作成すると、コンパイルが成功します。

Functions

このステップでは、Neptuneを操作するAWS Lambdaを作成します。Lambda functionsを作成する前に、次のコマンドで Lambda layerを作成して、 Gremlin libraryをインポートします。詳細は、Create a Lambda Layerを参照してください。

  1. 以下のコマンドでLamda Layerを作成します。
    $ amplify add function
    ? Select which capability you want to add: Lambda layer (shared code & resource used across functions)
    ? Provide a name for your Lambda layer: gremlin
    ? Select up to 2 compatible runtimes: NodeJS
    ? The current AWS account will always have access to this layer.
    Optionally, configure who else can access this layer. (Hit <Enter> to skip) Specific AWS accounts
    ? Provide a list of comma-separated AWS account IDs: ************ # Your own AWS Account
    
    ✅ Lambda layer folders & files updated:
    amplify/backend/function/gremlin
    
    Next steps:
    Include any files you want to share across runtimes in this folder:
    amplify/backend/function/gremlin/opt
    -----
    
    # Install gremlin package into the lambda layer
    $ cd amplify/backend/function/gremlin/opt/nodejs/ # create nodejs/ directory if there is not
    $ npm init # if you do not have package.json file here
    $ npm install gremlin
    $ cd ~/environment/react-amplify-neptune-workshop/
    
  2. getGraphDataのLambda functionを作成します。
    $ amplify add function
    Select which capability you want to add: Lambda function (serverless function)
    ? Provide an AWS Lambda function name: getGraphData
    ? Choose the runtime that you want to use: NodeJS
    ? Choose the function template that you want to use: Hello World
    Available advanced settings:
    - Resource access permissions
    - Scheduled recurring invocation
    - Lambda layers configuration
    ? Do you want to configure advanced settings? Yes
    Do you want to access other resources in this project from your Lambda function? Yes
    ? Select the category 
    You can access the following resource attributes as environment variables from your Lambda function
    ENV
    REGION
    ? Provide existing layers or select layers in this project to access from this function (pick up to 5): gremlin
    ? Select a version for gremlin: 1
    ? Do you want to edit the local lambda function now? Yes
    Successfully added resource getGraphData locally.
  3. Lambda functionを追加した後に、以下のコマンドを実行してLambda functionに関するCloudFormation templateを修正します。Amplifyはこのテンプレートを利用してLambda環境をデプロイします。テンプレートの設定を変更した場合は、コンソール画面から設定変更しないでください。ここでは、ご自身のNeptuneインスタンスのリーダーエンドポイント、セキュリティグループID、およびサブネットIDの値を指定する必要があります。
    $ sed -i 's/"REGION":{"Ref":"AWS::Region"}/"NEPTUNE_ENDPOINT": "your-neptune-reader-endpoint","NEPTUNE_PORT": "8182"/g' amplify/backend/function/getGraphData/getGraphData-cloudformation-template.json
    $ sed -i '/"Environment"/i "MemorySize": 1024,"VpcConfig": {"SecurityGroupIds": ["your-neptune-sg-id"],"SubnetIds": ["your-neptune-subnet-id","your-neptune-subnet-id","your-neptune-subnet-id","your-neptune-subnet-id","your-neptune-subnet-id","your-neptune-subnet-id"]},' amplify/backend/function/getGraphData/getGraphData-cloudformation-template.json
    $ sed -i '/"AssumeRolePolicyDocument"/i "ManagedPolicyArns": ["arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole","arn:aws:iam::aws:policy/NeptuneReadOnlyAccess"],' amplify/backend/function/getGraphData/getGraphData-cloudformation-template.json
    
  4. 以下のコマンドで、Lambda functionのindex.jsを書き換えます。
    $ wget https://aws-database-blog.s3.amazonaws.com/artifacts/DBBLOG-1462/lambda/getGraphData/index.js -O amplify/backend/function/getGraphData/src/index.js 

    以下はgetGraphDataのコードです。AWS AppSyncからLambda functionは実行され、Gremlinを利用してNeptuneにアクセスしてノードやエッジといったグラフ情報を取得します。

    const gremlin = require('gremlin');
    const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;
    const Graph = gremlin.structure.Graph;
    const P = gremlin.process.P
    const Order = gremlin.process.order
    const Scope = gremlin.process.scope
    const Column = gremlin.process.column
    
    exports.handler = async (event, context, callback) => {
        const dc = new DriverRemoteConnection(`wss://${process.env.NEPTUNE_ENDPOINT}:${process.env.NEPTUNE_PORT}/gremlin`,{});
        const graph = new Graph();
        const g = graph.traversal().withRemote(dc);
        try {
            const result = await g.V().toList()
            const vertex =  result.map(r => {
                return {'id':r.id,'label':r.label}
            })
            const result2 = await g.E().toList()
            const edge = result2.map(r => {
                console.log(r)
                return {"source": r.outV.id,"target": r.inV.id,'value':r.label}
            })
            return {'nodes':vertex,"links":edge}
          } catch (error) {
            console.error(JSON.stringify(error))
            return { error: error.message }
          }
    }
  5. getGraphDataのLambda functionの設定は完了しました。同様にステップ2から4の手順を実行して、以下のLambda functionを作成します(コード内のfunction名を書き換えてください)。
    1. getInfoNeptune
    2. queryNeptune
    3. registerNeptune (ステップ3のsed コマンドのyour-neptune-reader-endpointyour-neptune-writer-endpointに書き換えてください。)
  6. Lambda functionsのセットアップを完了するために、以下のコマンドを実行してcomponents.zipを AWS Cloud9にダウンロードします。
    $ wget https://aws-database-blog.s3.amazonaws.com/artifacts/DBBLOG-1462/components.zip && unzip components.zip -d src

GraphQL API

ここまでのステップで、認証用のユーザープールとNeptuneにクエリするバックエンドのLambda functionsを作成してきました。このステップではAmplifyアプリケーションに GraphQL API を追加します。

  1. 以下のコマンドを実行して、GraphQL API テンプレートを作成します。
    $ amplify add api
    ? Please select from one of the below mentioned services: GraphQL
    ? Provide API name: neptune
    ? Choose the default authorization type for the API Amazon Cognito User Pool
    Use a Cognito user pool configured as a part of this project.
    ? Do you want to configure advanced settings for the GraphQL API No, I am done.
    ? Do you have an annotated GraphQL schema? No
    ? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)
    
    The following types do not have '@auth' enabled. Consider using @auth with @model
    - Todo
    Learn more about @auth here: https://docs.amplify.aws/cli/graphql-transformer/auth
    ...
    GraphQL schema compiled successfully.
  2. テンプレートを作成後、次のコマンドでGraphQLスキーマを上書きしてコンパイルします。
    Queryで、検索結果や検索ワードに関する情報、例えば所属、製品、学会などの情報を取得できます。Mutationで、Neptuneにノードやエッジを登録します。

    type Result {
      name: String!
    }
    
    type Profile {
      search_name: String
      usage: String
      belong_to: String
      authored_by: String
      affiliated_with: String
      people: String
      made_by: String
    }
    
    type Register {
      result: String
    }
    type GraphInfo {
      nodes: [Nodes]
      links: [Links]
    }
    
    type Nodes {
      id: String
      label: String
    }
    
    type Links {
      source: String
      target: String
      value: String
    }
    type Query {
      getResult(name: String!, value: String!): [Result]
        @function(name: "queryNeptune-${env}")
        @auth(rules: [{ allow: private, provider: userPools }])
    
      getProfile(name: String!, value: String!): [Profile]
        @function(name: "getInfoNeptune-${env}")
        @auth(rules: [{ allow: private, provider: userPools }])
      getGraphInfo(value: String!): GraphInfo
        @function(name: "getGraphData-${env}")
        @auth(rules: [{ allow: private, provider: userPools }])
    }
    
    type Mutation {
      registerInfo(
        value: String!
        name: String
        edge: String
        vertex: String
        property: String
        source: String
        sourceLabel: String
        destination: String
        destLabel: String
      ): [Register]
        @function(name: "registerNeptune-${env}")
        @auth(rules: [{ allow: private, provider: userPools }])
    }
    $ amplify api gql-compile
    ...
    GraphQL schema compiled successfully.
    
  3. amplify pushで変更をプッシュします。
    $ amplify push

アプリケーションのデプロイ

次のコマンドを実行してアプリケーションをホスティングします。Hosting with Amplify Consoleを指定して、Manual deploymentを行います。

$ amplify add hosting
? Select the plugin module to execute Hosting with Amplify Console (Managed hosting with custom domains, Continuous deploym
ent)
? Choose a type Manual deployment
You can now publish your app using the following command:
Command: amplify publish

最後にアプリケーションをデプロイします。

$ amplify publish

アプリケーションが公開したら、その操作性とレスポンスの速さを是非体感してください。

Clean up

今後の請求を避けるために、ブログで紹介したリソースを削除してください。

  1. 以下のコマンドを実行してAWS Amplifyで作成したリソースを削除します。
    $ amplify delete
    ? Are you sure you want to continue? This CANNOT be undone. (This would delete all the environments of the project from the cloud and wipe out all the local files c
    reated by Amplify CLI) Yes
    ⠋ Deleting resources from the cloud. This may take a few minutes...
  2. 以下のコマンドを実行してAmazon Neptuneのクラスターとインスタンスを削除します。
    $ aws neptune delete-db-instance --db-instance-identifier neptune
    $ aws neptune delete-db-instance --db-instance-identifier read-neptune
    $ aws neptune delete-db-cluster --db-cluster-identifier database-1 --skip-final-snapshot
  3. Amazon S3コンソールからノードとエッジのデータファイルを格納したバケットを選択します。
  4. Emptyを選択して、Deleteします。
  5. IAMのコンソールから、バルクロードで利用したロール(NeptuneLoadFromS3)を選択してDelete roleで削除します。
  6. VPCコンソールから、作成したVPC endpointエンドポイントを作成してDelete Endpointで削除します。
  7. AWS Cloud9コンソールから、作成したAWS Cloud9環境を選択して、Deleteで削除します。

Summary

このブログでは、AWS Amplify を利用してNeptuneを操作するアプリケーションを開発する方法を紹介しました。Neptuneデータベースを作成し、認証、バックエンドのLambda functions、GraphQL API・関数を追加しました。

NeptuneとAmplifyを利用してアプリケーションを開発するには、NeptuneAmplifyのユーザーガイドを参照してください。

英訳版はAWS Database Blogのこちらに掲載しています。


著者について

石尾千晶(Chiaki Ishio) はプロセス製造・ヘルスケア・ライフサイエンスチームのソリューションアーキテクトです。カスタマーへのAWSでのシステム設計や構築支援に従事しています。 プライベートでは、ピアノ演奏を楽しんでいます。

 

 

 

小泉 秀徳(Hidenori Koizumi)は、パブリックセクターのプロトタイピングソリューションアーキテクトです。理学のバックグラウンド(生物学、化学など)を活かした研究領域でのソリューション作成を得意としています。最近では、AWS AmplifyやAWS CDKでのアプリケーション開発を行っています。趣味は旅行と写真撮影です。