neo4j 実例で学ぶCypher -1-
はじめに前提的なこと
- 楽天のような店子をたくさん持つプラットフォーマーの立場で考えます
- たくさんのユーザが色々なショップで色々な商品を購入し、その購入履歴データを保持している
-
前回から引き続きです
サンプルデータ
データ構造は下記
データ構造は下記
CSVとしては下記
category.csv
category_id:ID,name,:LABEL
cate1,カテゴリ1,category
cate2,カテゴリ2,category
shops.csv
shop_id:ID,name,category_id,:LABEL
shop1,ショップA,cate1,shop
shop2,ショップB,cate1,shop
shop3,ショップC,cate2,shop
item.csv
item_id:ID,name,shop_id,:LABEL
item1,商品A,shop1,item
item2,商品B,shop1,item
item3,商品C,shop2,item
item4,商品D,shop3,item
item5,商品E,shop3,item
orders.csv
order_id:ID,date,user_id,shop_id,category_id,price,item_id,:LABEL
order1,2016-04-02,user1,shop1,cate1,9500,item1,order
order2,2016-04-03,user2,shop1,cate1,1000,item1,order
order3,2016-04-04,user3,shop1,cate1,1200,item2,order
order4,2016-04-05,user4,shop2,cate1,15000,item3,order
order5,2016-03-22,user1,shop3,cate2,2000,item4,order
order6,2016-02-11,user2,shop3,cate2,4000,item4,order
order7,2016-03-25,user1,shop3,cate2,5000,item5,order
users.csv
user_id:ID,name,email,age:int,industry,gender,:LABEL
user1,user_name1,[email protected],37,サービス業,male,user
user2,user_name2,[email protected],17,ネットサービス,male,user
user3,user_name3,[email protected],27,公務員,female,user
user4,user_name4,[email protected],44,公務員,male,user
データ投入は
こんな感じで
neo4j-import --into /usr/local/Cellar/neo4j/2.3.2/libexec/data/graph5.db --nodes category.csv --nodes items.csv --nodes orders.csv --nodes shops.csv --nodes users.csv
リレーション
ユーザと購入を紐付け
MATCH (o:order),(u:user)
WHERE o.user_id = u.user_id
CREATE (u)-[:BUY]->(o);
購入データと商品を紐付け
MATCH (o:order),(i:item)
WHERE o.item_id = i.item_id
CREATE (o)-[:ORDER]->(i);
お店と商品を紐付け
MATCH (s:shop),(i:item)
WHERE s.shop_id = i.shop_id
CREATE (i)-[:PART]->(s);
お店とお店のジャンルを紐付け
MATCH (c:category),(s:shop)
WHERE c.category_id = s.category_id
CREATE (s)-[:CATE]->(c);
抽出したいデータからCypherを考える
購入確率の高いユーザを抽出する
- 過去の購入履歴から電化製品カテゴリのショップで購入したことのあるユーザを電化製品好きのユーザとする
- 新しい電化製品の販売が始まってが、まだ購入していない電化製品好きのユーザを抽出する
サンプルデータから正解を考える
- まず
カテゴリ1
を電化製品を扱ってるショップのカテゴリとする
- 新しい電化製品の販売が始まったお店を
ショップA
とする
-
ショップA
の購入データは無いが、カテゴリ1
=電化製品カテゴリに分類されるお店での購入履歴のあるユーザを抽出すれば良い
- 図からたどると
user4
が抽出されれば正解
Cypherで書き正解を出す
neo4j-sh (?)$ MATCH (u:user)-->(o:order)-->(i:item)-->(s:shop)-->(c:category)
> WHERE NOT s.name="ショップA" AND c.name="カテゴリ1"
> RETURN u.name;
+--------------+
| u.name |
+--------------+
| "user_name4" |
+--------------+
- 回答が一致
購入者の内訳で男女べつにどのくらいの割合かを知りたい
- ショップAに絞って考える
サンプルデータから正解を考える
- ショップAで購入しているユーザはuser1,user2,user3
- user1はmale,user2はmale,user3はfemale
- なのでmale:2,female:1となる
Cypherで書き正解を出す
-
UNION ALL
で続けて出してしまう
neo4j-sh (?)$ MATCH (u:user)-->(o:order)-->(i:item)-->(s:shop)-->(c:category)
> WHERE s.name="ショップA" AND u.gender='male'
> RETURN count(u)
> UNION ALL
> MATCH (u:user)-->(o:order)-->(i:item)-->(s:shop)-->(c:category)
> WHERE s.name="ショップA" AND u.gender='female'
> RETURN count(u)
> ;
+----------+
| count(u) |
+----------+
| 2 |
| 1 |
+----------+
2 rows
21 ms
- 回答が一致
購入者の内訳で誰が何個購入しているのかを知りたい
- ショップCに絞って考える
サンプルデータから正解を考える
- ショップAで購入しているユーザはuser1,user2
- user1は商品Dと商品Eを購入
- user2は商品Dを購入
- なのでuser1は2回購入、user2は1回購入となる
Cypherで書き正解を出す
neo4j-sh (?)$ MATCH (u:user)-->(o:order)--(i:item)-->(s:shop)
> WHERE s.name="ショップC"
> RETURN u.name, count(o) as order_cnt;
+--------------------------+
| u.name | order_cnt |
+--------------------------+
| "user_name1" | 2 |
| "user_name2" | 1 |
+--------------------------+
2 rows
- 回答が一致
まとめ、雑感
- relationshipをもっと貼ってみてCypher考えた方が良さそう
- relationshipの貼り方次第的な感覚も出てきた
- SQL書くより簡単なのは確か
カテゴリ1
を電化製品を扱ってるショップのカテゴリとするショップA
とするショップA
の購入データは無いが、カテゴリ1
=電化製品カテゴリに分類されるお店での購入履歴のあるユーザを抽出すれば良いuser4
が抽出されれば正解neo4j-sh (?)$ MATCH (u:user)-->(o:order)-->(i:item)-->(s:shop)-->(c:category)
> WHERE NOT s.name="ショップA" AND c.name="カテゴリ1"
> RETURN u.name;
+--------------+
| u.name |
+--------------+
| "user_name4" |
+--------------+
UNION ALL
で続けて出してしまうneo4j-sh (?)$ MATCH (u:user)-->(o:order)-->(i:item)-->(s:shop)-->(c:category)
> WHERE s.name="ショップA" AND u.gender='male'
> RETURN count(u)
> UNION ALL
> MATCH (u:user)-->(o:order)-->(i:item)-->(s:shop)-->(c:category)
> WHERE s.name="ショップA" AND u.gender='female'
> RETURN count(u)
> ;
+----------+
| count(u) |
+----------+
| 2 |
| 1 |
+----------+
2 rows
21 ms
neo4j-sh (?)$ MATCH (u:user)-->(o:order)--(i:item)-->(s:shop)
> WHERE s.name="ショップC"
> RETURN u.name, count(o) as order_cnt;
+--------------------------+
| u.name | order_cnt |
+--------------------------+
| "user_name1" | 2 |
| "user_name2" | 1 |
+--------------------------+
2 rows
- relationshipをもっと貼ってみてCypher考えた方が良さそう
- relationshipの貼り方次第的な感覚も出てきた
- SQL書くより簡単なのは確か
Author And Source
この問題について(neo4j 実例で学ぶCypher -1-), 我々は、より多くの情報をここで見つけました https://qiita.com/nakamura-tsuyoshi/items/4a0cbf20ce9ba4c934b9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .