LoginSignup
20
12

More than 5 years have passed since last update.

Rubyからneo4jrb/neo4jを使ってneo4jにアクセスする

Last updated at Posted at 2015-01-03

はじめに

Rubyからneo4jにアクセスする方法を調べているとneographyを使った方法がわりとヒットします。

これらを読みつつちょっと使ってみたのですが、あまり性に合わなかったので、他の方法を探してみました。その結果、neo4jrb/neo4jを使った方がいろいろスッキリしたので基本的な使い方についてまとめてみます。

neo4jrb/neo4j自体はいわゆるグラフDBのNeo4jのActive Modelラッパーだそうです。このエントリーでは、neo4jrb/neo4jが内部で使用しているneo4j/neo4j-coreを直接使ってみました。現時点でneo4j-coreはv3.0です。

一次情報はドキュメントを見てください。

前提条件

以下の条件のもとで環境の準備を行なっていきます。

  • LinuxもしくはMac OSX
  • Ruby環境(今回は2.1.0を使っています)

Gemの準備

gemをインストールするには、以下のような内容のGemfileを作成してbundle installします。

source 'https://rubygems.org'

gem 'neo4j'
gem 'rake'

Neo4jのインストール

インストール方法はいくつかありますが、今回はneo4jrb/neo4jに含まれるRakefileを利用した方法でインストールします。

以下の内容を含むRakefileを作成します。

load 'neo4j/tasks/neo4j_server.rake'

次にNeo4jをインストールして起動します。Neo4jのバージョンについては、こちらを確認します。なお、この方法はプロジェクト内にDBを構築するので開発環境向けです。

$ rake neo4j:install[community-2.1.6]
$ rake neo4j:start

運用環境向けなど、その他のインストールおよび起動方法についてはこちらをご覧ください。

準備が整ったので、以降DBにアクセスしていきます。

Session

DBのセッションをオープンします。

require "neo4j-core"
session = Neo4j::Session.open(:server_db)

Transaction

トランザクションを利用してDBに対する複数の操作を管理することができます。

l1 = "北斗神拳"
l2 = "伝承者"
Neo4j::Transaction.run do
  nr = Neo4j::Node.create({name: "リュウケン"}, l1, l2)
  nk = Neo4j::Node.create({name: "コウリュウ"}, l1)
  # 複数の処理
  # :
  # :
end

Node

ノードを作成してプロパティとラベルを設定します。

l1 = "北斗神拳"
l2 = "伝承者"
labels = [l1, l2]
# プロパティを一つ設定。ラベルを複数設定。
nr = Neo4j::Node.create({name: "リュウケン"}, l1, l2)
# プロパティを後から設定
nk = Neo4j::Node.create({name: "コウリュウ"}, l1)
n1 = Neo4j::Node.create({name: "ラオウ"}, l1)
n1[:hero] = false
# 複数のキーを持つ連想配列でプロパティを設定。ラベルは一つだけ設定。
props_n2 = {
  name: "トキ",
  hero: false,
}
n2 = Neo4j::Node.create(props_n2, l1)
n3 = Neo4j::Node.create({name: "ジャギ", hero: false}, l1)
# ラベルを配列展開して設定
n4 = Neo4j::Node.create({name: "ケンシロウ"}, *labels)
n4[:hero] = true

Relationship

ノード間にリレーションをはります。

# プロパティを後から設定
rel = nr.create_rel(:student, n1, {order: 1})
rel[:inherit] = false
# 複数のキーを持つ連想配列でプロパティを設定
nr.create_rel(:student, n4, {order: 4, inherit: true})

LabelとIndex

ラベルにインデクスを設定します。

l1 = "北斗神拳"
l2 = "伝承者"
labels = [l1, l2]
i1 = Neo4j::Label.create(l1)
i1.create_index(:name)
i2 = Neo4j::Label.create(l2)
i2.create_index(:name)

ラベルでノードを検索します。

# Node idでNodeを検索
Neo4j::Node.load(n4.neo_id)

# LabelとnameでNodeを検索
Neo4j::Label.find_nodes(l1, :name, "ジャギ")

# Labelを指定して全Node検索
Neo4j::Label.find_all_nodes(l2)

# 指定したNodeに接続する全Relationshipを検索
nodes = Neo4j::Label.find_nodes(l2, :name, "リュウケン")
nr = nodes.first
nodes = nr.rels
nodes.each{|n|
  puts "neo_id:#{n.neo_id} props:#{n.props}"
}

# outgoingなRelationshipを検索
nodes = Neo4j::Label.find_nodes(l2, :name, "リュウケン")
nr = nodes.first
rels = nr.rels(dir: :outgoing)
rels.each{|r|
  puts "neo_id:#{r.neo_id} rel_type:#{r.rel_type} props:#{r.props}"
}

# outgoingなRelationshipの先のNodeを検索
nodes = Neo4j::Label.find_nodes(l2, :name, "リュウケン")
nr = nodes.first
nodes = nr.nodes(dir: :outgoing)
nodes.each{|n|
  puts "neo_id:#{n.neo_id} labels:#{n.labels} props:#{n.props}"
}

Queries

生のCypherが使える他、DSLによりクエリを発行することができます。

# Relationshipにinherit=trueをもつパスを検索
inherit_path = Neo4j::Session.query("MATCH (s)-[r {inherit:true}]->(g) RETURN s, r, g")
inherit_path.each{|path|
  path.each{|n|
    puts "neo_id:#{n.neo_id} props:#{n.props}"
  }
}

# パラメータを用いた検索
inherit_path = Neo4j::Session.query("MATCH (s)-[r {inherit:{value}}]->(g) RETURN s, r, g", value: true)
inherit_path.each{|path|
  path.each{|n|
    puts "neo_id:#{n.neo_id} props:#{n.props}"
  }
}

# Label=伝承者のNodeを検索(return)
query = Neo4j::Session.query.match(n: l2)
res = query.return(:n)
res.each{|path|
  path.each{|n|
    puts "neo_id:#{n.neo_id} labels:#{n.labels} props:#{n.props}"
  }
}

# Label=伝承者のNodeのプロパティ(name)を指定して列挙
query = Neo4j::Session.query.match(n: l2)
res = query.return(n: [:name])
res.each{|path|
  path.each{|n|
    puts "name:#{n}"
  }
}

# name=リュウケンのNodeを検索(pluck)
arr = query.pluck(:n)
arr.each{|n|
  puts "neo_id:#{n.neo_id} props:#{n.props}"
}

さいごに

サンプルコードをGitHubにあげておきました。

データはこんな感じになります。全Nodeに北斗神拳Labelを設定しているのですが、伝承者Labelを設定しているNodeは北斗神拳Labelが設定されていないように見えるのがちょっとアレですが。

neo4j-example.png

北斗神拳は一子相伝。
ただこれが言いたかった。

inherit.png

なお、このデータはWikipediaの情報を元に作成しています。

20
12
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
20
12