Amazon Neptuneにデータを入れて可視化してみたい② ~クエリと可視化編~

記事タイトルとURLをコピーする

こんにちは!篠﨑です。

今回はAmazon Neptuneにデータを入れて可視化してみたい① ~準備・データ追加編~の続編です。 データの挿入その準備について書いていますので、①を読んでもらえるとやっていることが分かりやすいかと思います。

本シリーズの目標は基本的なgremlinのクエリを使えるようになることで、数記事にわたって以下3点について書いています。

  • データの挿入
  • データの取得
  • 可視化

今回はその中でもデータの取得可視化について書いていきます。

※ 本ブログは、「Amazon Neptuneってどんなことができるの?」という疑問を持つ方や「とりあえず作ってみたけど、この後どうしたらいいの?」という方向けとなっています。クエリの内容の詳細については割愛させていただいております。 詳細はAWS公式ドキュメントもしくはTinkerPop公式ドキュメントをご確認ください。

やること

前回同様、サーバーワークスの人ってどんなカテゴリーでブログ書いているの??を題材にAmazon Neptuneを利用します。

今回は前回入れたデータからクエリを投げていろいろな検索をしたいと思います。 クエリの結果を図にしてみるところまでやります。

  1. フォローしているユーザーを調べる
  2. フォローしているユーザーの書いたカテゴリーを調べる
  3. 一番多く書かれたカテゴリーを調べる
  4. あるユーザーと似たユーザーを調べる

※ フォローはフィクションです。実際とは関係なく、面白そうなので入れてみました。

前提条件

冒頭にあるように、本ブログはAmazon Neptuneにデータを入れて可視化してみたい① ~準備・データ追加編~の続編です。

Notebookを開き、データが入っている状態からスタートとなりますので、ご了承ください。

グラフDBについて

これまでほとんど触れてきませんでしたが、検索等をしていく中で必要になりますので、グラフDBの構成要素について簡単に触れます。

f:id:swx-shinozaki:20220126112858p:plain

かなりざっくりですが、グラフDBは頂点と辺で構成されており、それぞれVertex、Edgeで表現されます。

前回入れたデータの中でもカテゴリー一覧のデータやUser一覧のデータは頂点で、図の丸部分に当たります。

サーバーワークスの人同士の関連付けやFollowの関係を表すデータは辺で、矢印部分に当たります。

頂点や辺ではそれぞれ、IDやLabel、Propertyを割り当てて、その情報をもとにデータの判別をしています。 例えば今回、ユーザー情報のIDには1から21までの数値、LabelにUser、Propertyにnameとしてそれぞれの名前を入力しています。

かなり簡単ではありますが、このことをもとに、どんな情報が取れるか見てもらえたらと思います。

クエリを投げる

まずは全体を見てみる

ブログ①からそのままの場合、下のコマンドを入力すると結果がv[1]からv[interest79]まで入っているかと思います。確認してみましょう。

%%gremlin
g.V()

次に辺が入っているか確認します。FollowやInterestedInが出力されればOKです。

%%gremlin
g.E()

※ エラーが出てきた場合、ブログ①にある手順を踏んで、データを入れてください。

フォローしているユーザーを調べる

今回は、User2がフォローしている人を調べます。

%%gremlin
g.V().has('User', 'name', 'User1').out('Follow').valueMap()

下のように2人でてきました。

1  {'name': ['User8']}
2  {'name': ['User21']}

グラフでも見てみましょう

%%gremlin
g.V().has('name', 'User2').out('Follow').path().by('name')

このように見えました。

f:id:swx-shinozaki:20220131152220p:plain

フォローしているユーザーの書いたカテゴリーを調べる

まず、対象のユーザーの書いたカテゴリーを表示してみます

%%gremlin
g.V().has('name', 'User2').out('Follow').out('InterestedIn').valueMap()

下のように出てきました。日本語が文字化けしてしまってますね、、、

1    {'name': ['AWS']}
2   {'name': ['���S�Ҍ���']}
3   {'name': ['�v���O���~���O']}
4   {'name': ['�Ǐ����z��']}
5   {'name': ['re:Invent 2021']}
6   {'name': ['Amazon VPC']}
7   {'name': ['Amazon VPC Network Access Analyzer']}
8   {'name': ['AWS']}
9   {'name': ['re:Invent 2021']}
10  {'name': ['AI']}

S3の元データをUTF-8に変更することで文字化けを解消することができました。

※ S3から挿入したInterest.csvとUserInterest.csvの値をクリアしてから入れることで正常に行うことができます。

↓クリアする際のクエリ↓

%%gremlin
g.V().hasLabel('Interest').drop()

もう一度実行して下のように出ればOKです。

1    {'name': ['AWS']}
2   {'name': ['初心者向け']}
3   {'name': ['プログラミング']}
4   {'name': ['読書感想文']}
5   {'name': ['re:Invent 2021']}
6   {'name': ['Amazon VPC']}
7   {'name': ['Amazon VPC Network Access Analyzer']}
8   {'name': ['AWS']}
9   {'name': ['re:Invent 2021']}
10  {'name': ['AI']}
... (12まで)

図で表示

%%gremlin
g.V().has('name', 'User2').out('Follow').out('InterestedIn').path().by('name')

f:id:swx-shinozaki:20220131153940p:plain

一番多く書かれたカテゴリーを調べる

%%gremlin -p v
g.V().hasLabel('Interest').order().by(inE().count(), desc).limit(10).project('Interest', 'count').by('name').by(inE('InterestedIn').count())

AWSというカテゴリーで一番多く書かれていることが分かりました。

1    {'count': 12, 'Interest': 'AWS'}
2   {'count': 6, 'Interest': 'AWS Lambda'}
3   {'count': 4, 'Interest': 'セキュリティ'}
4   {'count': 4, 'Interest': 're:Invent 2021'}
5   {'count': 3, 'Interest': 'EC2'}
6   {'count': 3, 'Interest': 'Amazon S3'}
7   {'count': 2, 'Interest': 'AWS Cost Explorer'}
8   {'count': 2, 'Interest': 'AWS Amplify'}
9   {'count': 2, 'Interest': '初心者向け'}
10  {'count': 2, 'Interest': 'AWS CLI'}

あるユーザーと似たおすすめのユーザーを調べる

最後に、自分の興味に一番近いカテゴリーを書いている人を探していきます。

例えば、「セキュリティ」や「DNS」、「Lambda」に興味がある場合、どんな人と興味が近いのかを調べてみたいと思います。

初めに、ユーザーの作成をします。 ここでは、調べたいカテゴリーに興味を持ったユーザーを作成します

%%gremlin
g.addV('User').property('name', 'User30').property(id, '30').as('user').
V().has('Interest', 'name', 'DNS').as('dns').
V().has('Interest', 'name', 'セキュリティ').as('sec').
V().has('Interest', 'name', 'AWS Lambda').as('lambda').
addE('InterestedIn').from('user').to('dns').
addE('InterestedIn').from('user').to('sec').
addE('InterestedIn').from('user').to('lambda')

次にユーザーの頂点と興味の辺が入っていることを確認します

%%gremlin
g.V().has('name','User30').out()

最後に検索するクエリを投げます

%%gremlin
g.V().has('name', 'User30').as('user').
out('InterestedIn').in('InterestedIn').where(neq('user')).values('name').groupCount().order(local).by(values, desc).next()

下のように出たらOKです。

1    {'User19': 3}
2   {'User7': 2}
3   {'User16': 1}
4   {'User2': 1}
5   {'User10': 1}

ここで出てくる数字はブログで興味のある記事を書いたカテゴリーの種類の数を表します。

User19の人と興味が近いことが分かりますね!

このようにすることで、例えば、新たにブログを書いた人と似た人をお勧めとして出すことができたりします。

終わりに

Neptuneでクエリの方法については以上となります。

Gremlinのクエリについては以下ソースを参考にしています。クエリについてさらに深堀する際に参照いただければと思います。

Amazon Neptune グレムリン基準準拠 - Amazon Neptune

TinkerPop Documentation

graph-notebook/Blog Workbench Visualization.ipynb at main · aws/graph-notebook · GitHub

graph-notebook/Air-Routes-Gremlin.ipynb at main · aws/graph-notebook · GitHub

ということで、こちらのシリーズについては終わりとなります。 Amazon Neptuneは少しハードルを高く感じている方も多いかと思いますが、このブログが足掛かりとなっていただけたらと思います。

篠﨑 勇輔(書いた記事を見る)

クラウドインテグレーション部 SRE2課

入社4年目