0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【後編】Amazon Neptune で EC サイトの OWL オントロジーを構築する(SPARQL クエリ実行環境)

0
Posted at

はじめに

前編では Neptune クラスターの構築、OWL オントロジーの設計、データ投入まで行いました。

後編では、セッションマネージャー経由で EC2 から直接 SPARQL を叩ける環境 を構築し、様々なクエリ例を紹介します。

構成図

マネジメントコンソール
    │ Session Manager
    ▼
┌──────────────────────────────────────────────────┐
│  VPC (us-east-1)                                  │
│                                                    │
│  ┌─────────────────┐      ┌───────────────────┐  │
│  │  EC2 (t3.micro) │─8182→│  Neptune (SPARQL) │  │
│  │  sparql.sh      │      │  472 triples      │  │
│  └─────────────────┘      └───────────────────┘  │
│                                                    │
└──────────────────────────────────────────────────┘

Step 7: EC2 インスタンスの構築

IAM ロール(SSM用)

aws iam create-role --role-name NeptuneEC2SSMRole \
  --assume-role-policy-document '{
    "Version":"2012-10-17",
    "Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]
  }'

aws iam attach-role-policy --role-name NeptuneEC2SSMRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

aws iam create-instance-profile --instance-profile-name NeptuneEC2SSMProfile
aws iam add-role-to-instance-profile \
  --instance-profile-name NeptuneEC2SSMProfile \
  --role-name NeptuneEC2SSMRole

EC2 起動

# 最新 Amazon Linux 2023 AMI を取得
AMI_ID=$(aws ec2 describe-images --owners amazon \
  --filters "Name=name,Values=al2023-ami-2023.*-x86_64" "Name=state,Values=available" \
  --query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
  --output text --region us-east-1)

# Neptune と同じ VPC/SG に起動
aws ec2 run-instances \
  --image-id "$AMI_ID" \
  --instance-type t3.micro \
  --subnet-id <SAME_SUBNET_AS_NEPTUNE> \
  --security-group-ids <SG_ID> \
  --iam-instance-profile Name=NeptuneEC2SSMProfile \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=neptune-sparql-client}]' \
  --metadata-options "HttpTokens=required,HttpEndpoint=enabled" \
  --region us-east-1

SSH キーは不要です。セッションマネージャー経由でアクセスするため、インバウンドのポート22を開ける必要もありません。

SSM 接続確認

aws ec2 wait instance-running --instance-ids <INSTANCE_ID> --region us-east-1

# SSM に登録されるまで待機(通常1分以内)
aws ssm describe-instance-information \
  --filters "Key=InstanceIds,Values=<INSTANCE_ID>" \
  --query 'InstanceInformationList[0].PingStatus' --output text \
  --region us-east-1
# => "Online" になれば OK

Step 8: SPARQL スクリプトの配置

EC2 上に sparql.sh を配置して、ワンライナーで SPARQL が実行できるようにします。

スクリプト内容

sparql.sh
#!/bin/bash
# Neptune SPARQL Query Tool
NEPTUNE="https://<YOUR_NEPTUNE_ENDPOINT>:8182/sparql"

if [ -z "$1" ]; then
  echo "=== Neptune SPARQL Query Tool ==="
  echo ""
  echo "Usage: ./sparql.sh '<SPARQL query>'"
  echo ""
  echo "--- Sample Queries ---"
  echo ""
  echo '# Count all triples'
  echo "./sparql.sh 'SELECT (COUNT(*) as ?count) WHERE { ?s ?p ?o }'"
  echo ""
  echo '# List all customers by LTV'
  echo "./sparql.sh 'PREFIX : <http://example.org/ecommerce#> SELECT ?name ?tier ?ltv WHERE { ?c a :Customer ; :firstName ?fname ; :lastName ?lname ; :hasMembership ?t ; :lifetimeValue ?ltv . BIND(CONCAT(?fname, \" \", ?lname) AS ?name) BIND(STRAFTER(STR(?t), \"#\") AS ?tier) } ORDER BY DESC(?ltv)'"
  exit 1
fi

curl -s -X POST "$NEPTUNE" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Accept: application/sparql-results+json" \
  --data-urlencode "query=$1" | python3 -m json.tool

EC2 への配置(SSM 経由)

# ローカルで base64 エンコード
SCRIPT_B64=$(base64 < sparql.sh | tr -d '\n')

# SSM で配置
cat > ssm-deploy.json << EOF
{"commands": ["echo '${SCRIPT_B64}' | base64 -d > /home/ssm-user/sparql.sh", "chmod +x /home/ssm-user/sparql.sh"]}
EOF

aws ssm send-command \
  --instance-ids <INSTANCE_ID> \
  --document-name "AWS-RunShellScript" \
  --parameters file://ssm-deploy.json \
  --region us-east-1

Step 9: セッションマネージャーで SPARQL を実行

接続方法

  1. AWS マネジメントコンソール → EC2 → インスタンス neptune-sparql-client を選択
  2. 接続Session Manager接続
  3. シェルが開いたら:
cd /home/ssm-user

クエリ例

基本: 全トリプル数

./sparql.sh 'SELECT (COUNT(*) as ?count) WHERE { ?s ?p ?o }'

顧客一覧(LTV降順)

./sparql.sh 'PREFIX : <http://example.org/ecommerce#> SELECT ?name ?tier ?ltv WHERE { ?c a :Customer ; :firstName ?fname ; :lastName ?lname ; :hasMembership ?t ; :lifetimeValue ?ltv . BIND(CONCAT(?fname, " ", ?lname) AS ?name) BIND(STRAFTER(STR(?t), "#") AS ?tier) } ORDER BY DESC(?ltv)'

結果:

{
  "results": {
    "bindings": [
      {"name": {"value": "Frank Martinez"}, "tier": {"value": "Platinum"}, "ltv": {"value": "4500.0"}},
      {"name": {"value": "Bob Johnson"}, "tier": {"value": "Platinum"}, "ltv": {"value": "3200.75"}},
      {"name": {"value": "Alice Williams"}, "tier": {"value": "Gold"}, "ltv": {"value": "1800.0"}},
      ...
    ]
  }
}

Gold メンバー

./sparql.sh 'PREFIX : <http://example.org/ecommerce#> SELECT ?name ?email ?ltv WHERE { ?c a :Customer ; :hasMembership :Gold ; :firstName ?fname ; :lastName ?lname ; :email ?email ; :lifetimeValue ?ltv . BIND(CONCAT(?fname, " ", ?lname) AS ?name) } ORDER BY DESC(?ltv)'

カテゴリ別売上(OWL クラス階層を活用)

./sparql.sh 'PREFIX : <http://example.org/ecommerce#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> SELECT ?category (SUM(?lineTotal) AS ?revenue) WHERE { ?item a :OrderItem ; :containsProduct ?prod ; :lineTotal ?lineTotal . ?prod rdf:type ?type ; :category ?category . FILTER(?type IN (:ElectronicsProduct, :FurnitureProduct, :BookProduct)) } GROUP BY ?category ORDER BY DESC(?revenue)'

結果:

category revenue
Furniture $941.96
Electronics $589.93
Books $190.00

注文詳細(3ホップのグラフ走査)

./sparql.sh 'PREFIX : <http://example.org/ecommerce#> SELECT ?customer ?product ?amount ?region WHERE { ?order :orderedBy ?cust ; :totalAmount ?amount ; :inRegion ?reg ; :hasOrderItem ?item . ?cust :firstName ?fname ; :lastName ?lname . ?item :containsProduct ?prod . ?prod :productName ?product . BIND(CONCAT(?fname, " ", ?lname) AS ?customer) BIND(STRAFTER(STR(?reg), "#") AS ?region) } ORDER BY DESC(?amount)'

メンバーシップティア別平均 LTV

./sparql.sh 'PREFIX : <http://example.org/ecommerce#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT ?tierName (AVG(?ltv) AS ?avgLTV) (COUNT(?c) AS ?memberCount) WHERE { ?c a :Customer ; :hasMembership ?tier ; :lifetimeValue ?ltv . ?tier a owl:NamedIndividual, :MembershipTier ; rdfs:label ?tierName . } GROUP BY ?tierName ORDER BY DESC(?avgLTV)'

結果:

tier avgLTV members
Platinum $3,850 2
Gold $1,383 3
Silver $820 2
Bronze $235 2

クラス階層の確認

./sparql.sh 'PREFIX : <http://example.org/ecommerce#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT ?class ?superclass WHERE { ?class rdfs:subClassOf ?superclass . FILTER(isIRI(?superclass)) } ORDER BY ?superclass'

リピーター検出

./sparql.sh 'PREFIX : <http://example.org/ecommerce#> SELECT ?customer (COUNT(?order) AS ?orderCount) (SUM(?total) AS ?totalSpent) WHERE { ?order :orderedBy ?cust ; :totalAmount ?total . ?cust :firstName ?fname ; :lastName ?lname . BIND(CONCAT(?fname, " ", ?lname) AS ?customer) } GROUP BY ?customer ?cust HAVING (COUNT(?order) > 1)'

オントロジー全体抽出

./sparql.sh 'SELECT ?s ?p ?o WHERE { ?s ?p ?o } ORDER BY ?s ?p ?o'

クリーンアップ

# EC2
aws ec2 terminate-instances --instance-ids <INSTANCE_ID> --region us-east-1

# Lambda
aws lambda delete-function --function-name neptune-ontology-loader --region us-east-1

# Neptune(インスタンス → クラスターの順)
aws neptune delete-db-instance \
  --db-instance-identifier ecommerce-ontology-instance-1 \
  --skip-final-snapshot --region us-east-1
# インスタンス削除完了を待ってから:
aws neptune delete-db-cluster \
  --db-cluster-identifier ecommerce-ontology \
  --skip-final-snapshot --region us-east-1

# サブネットグループ(クラスター削除完了後)
aws neptune delete-db-subnet-group \
  --db-subnet-group-name neptune-ontology-subnet-group --region us-east-1

# セキュリティグループ(Lambda ENI 解放後、30秒程待つ)
aws ec2 delete-security-group --group-id <SG_ID> --region us-east-1

# IAM
aws iam remove-role-from-instance-profile \
  --instance-profile-name NeptuneEC2SSMProfile --role-name NeptuneEC2SSMRole
aws iam delete-instance-profile --instance-profile-name NeptuneEC2SSMProfile
aws iam detach-role-policy --role-name NeptuneEC2SSMRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam delete-role --role-name NeptuneEC2SSMRole
aws iam detach-role-policy --role-name NeptuneLambdaRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
aws iam delete-role --role-name NeptuneLambdaRole
aws iam delete-role-policy --role-name NeptuneS3LoadRole --policy-name NeptuneS3ReadPolicy
aws iam delete-role --role-name NeptuneS3LoadRole

Neptune インスタンスの削除に 5〜7分 かかります。クラスター削除はインスタンス削除完了後に実行してください。セキュリティグループは Lambda の ENI が解放されるまで削除できないため、30秒ほど待ってから実行してください。


まとめ

RDB と比較した Neptune + OWL の利点

観点 RDB Neptune + OWL
関係性の表現 外部キー(フラット) グラフ走査(多段ホップ)
型の階層 なし rdfs:subClassOf で推論可能
排他制約 CHECK制約 owl:AllDisjointClasses
列挙型 ENUM owl:oneOf で形式定義
スキーマの自己記述 ERD(外部ドキュメント) オントロジー自体がデータとして格納
多段JOIN 性能劣化 グラフ走査は一定性能

所感

  • Neptune + SPARQL は「データの意味を問い合わせる」用途に強い
  • OWL 制約はドキュメント代わりにもなる(スキーマがそのまま検索可能)
  • セッションマネージャー経由なら SSH キーの管理不要で手軽に検証できる
  • データ量が少ない場合は INSERT DATA で十分、バルクローダーは大量データ向け

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?