neo4j

アークスのためのNeo4j Cypher入門

More than 1 year has passed since last update.

TL;DR

PSO2のギャザリングを題材にNeo4jの使い方を練習してみたので勘所を書いておく。
ざっくり言うと、素材から料理を作って、料理で素材取得などのブーストを掛けるシステム。
RDBだと辛そうだけどグラフDBなら見通し良さそうなので試した。

Node

粒度

  • RDBで検索の主キーに使うものは片っ端からノードにすると楽な印象。
  • ノードは「ラベル」という大分類を持つので、種別ごとに整理できる。
  • 今回は4種類のラベルを作った(Category, Dish, Fish, Pick)

種類ごとのノード作成例

  • Dish (料理)
create (dish:Dish {name:"森林トマトのサラダ"})
create (dish:Dish {name:"森林アユのトマト煮"})

※Webインターフェースを使って入力する場合、createは1行ごとに実行すること。

  • Category
create (category:Category {name:"野菜"})
create (category:Category {name:"大型"})
create (category:Category {name:"魚類"})
create (category:Category {name:"小型"})
  • Pick (採取)
create (pick:Pick {name:"森林トマト"})
  • Fish (釣り)

※ゲーム内の扱いは「採取」で採れるものと同格。採るときにタイミング判定がある程度。なので同じ感じで用意しておく。

create (pick:Fish {name:"森林アユ"})

ここまでで出来るグラフ

MATCH (n) RETURN n LIMIT 25

make_nodes.png

Relationship

RelationshipにはPropertyを設定できる。

料理(Dish)と材料(Pick,Fish)

ひとまず「USE」として紐付けする。
材料ごとに使う個数を設定する。

  • 材料1種類の場合
match (dish:Dish {name:"森林トマトのサラダ"}),(pick:Pick {name:"森林トマト"})
merge (dish)-[roles:USE{number:10}]->(pick)
return dish,pick

relationship_1resource.png

  • 材料2種類の場合
match (dish:Dish {name:"森林アユのトマト煮"}),(pick:Pick {name:"森林トマト"}),(fish:Fish {name:"森林アユ"})
merge (dish)-[roles1:USE{number:10}]->(pick)
merge (dish)-[roles2:USE{number:10}]->(fish)
return dish,pick,fish

relationshipの仮引数の名称さえ分ければ何個でも書ける。

relationship_2resource.png

材料(Pick,Fish)と種類(Category)

  • 森林トマト

「野菜」で「大型」

match (pick:Pick {name:"森林トマト"}),(category1:Category {name:"野菜"}),(category2:Category {name:"大型"})
merge (pick)-[belong1:BELONG]->(category1)
merge (pick)-[belong2:BELONG]->(category2)
return pick,category1,category2

relationship_tomato.png

  • 森林アユ

「魚類」で「小型」

match (fish:Fish {name:"森林アユ"}),(category1:Category {name:"魚類"}),(category2:Category {name:"小型"})
merge (fish)-[belong1:BELONG]->(category1)
merge (fish)-[belong2:BELONG]->(category2)
return fish,category1,category2

relationship_ayu.png

料理(Dish)と種類(Category)

料理を食べると採取や釣りなどの材料に種類別ブーストが掛かる。
ブーストの効果時間や、追加効果をどう処理するかは未定なので今回は記載しない。でも恐らくノードにすると見やすそう。

  • 森林トマトのサラダ
match (dish:Dish {name:"森林トマトのサラダ"}),(category:Category {name:"野菜"})
merge (dish)-[boost:BOOST]->(category)
return dish,boost

relationship_boost_yasai.png

  • 森林アユのトマト煮
match (dish:Dish {name:"森林アユのトマト煮"}),(category:Category {name:"大型"})
merge (dish)-[boost:BOOST]->(category)
return dish,boost

relationship_tomatoni.png

まとめて表示

MATCH ()-[r]->() RETURN r LIMIT 25

summary.png

Wikiだとテーブル表現になってしまうので有機的な繋がりが見えないが、グラフDBならこんなに見やすくなる。

参考文献

Cypher Query Language(QL)-初級編 #neo4j https://www.creationline.com/lab/7685
PSO2ギャザリング(swiki) http://pso2.swiki.jp/index.php?%E3%82%AE%E3%83%A3%E3%82%B6%E3%83%AA%E3%83%B3%E3%82%B0#u614ae64
Relationship with Properties with Existing Nodes https://www.tutorialspoint.com/neo4j/neo4j_create_relationship_with_properties_with_existing_nodes.htm
is there a way to add multiple nodes with properties in Neo4j with Cypher https://stackoverflow.com/questions/21605388/is-there-a-way-to-add-multiple-nodes-with-properties-in-neo4j-with-cypher