`
cnetwei
  • 浏览: 173874 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

【转】Ruby中使用Neo4j——Neo4j.rb简介

 
阅读更多

【转】Ruby中使用Neo4j——Neo4j.rb简介

原帖地址:http://neo4j.tw/basic/index

 

安裝

資料定義 與 型別

基本搜尋

Neo4j與Neo4j.rb的差別
由於Neo4j預設可以選擇安裝為server或embeed的形式,故使用不同的語言會有不同的安裝方式.
Neo4j本身以Java撰寫,是獨立的Server形式並透過Restful的方式來呼叫.
如果我們打算使用Java,則我們可以直接使用Neo4j 以 Java Libraries (Jar)的形式來呼叫.
如果我們打算使用Ruby或Rails,那麼我們應該只以gem的方式安裝. 可以參考安裝neo4j.rb gem
對使用Ruby或Rails的人來說,如果不熟悉Java或只想先試試Neo4j.
那麼使用Neo4j.rb是一個非常快速並且優良的選擇. 雖然Neo4j.rb將Neo4j的Java libraries使用jRuby來呼叫而使得速度比不上Neo4j(純Java)本身.
但是快速上手及開發的精神就像使用Rails的精神一樣,當負載量到達一定的規模再轉移到純Neo4j,是件快速又簡單的事.

如果打算使用其他語言,請點選我看下面列表 :
Language
Clojure : 官方說明
Erlang : 官方說明
Gremlin : 官方說明
Groovy : 官方說明
Java (Object Mapping) : 官方說明
PHP : 官方說明
Python : 官方說明
Ruby (Restful) : 官方說明
Scala : 官方說明

Frameworks
Grails : 官方說明
Griffon : 官方說明
Qi4j : 官方說明
Roo : 官方說明

Restful
Neo4RestNet (.Net Rest Client) : 官方說明
Neo4RestSharp (.Net Rest Client) : 官方說明
Common Lisp REST client : 官方說明
PHP REST client : 官方說明
Python REST client : 官方說明
安裝Neo4j
安裝Neo4j並不太困難. 安裝方式提供Server 式及 Embedded 的方式. 下面我們將展示Mac及Linux的安裝.
Mac & Linux Server版
1. 點我下載Neo4j 1.2 Mac版

2. 解壓縮它,或將它移到你想要的目錄解壓縮它.
$> tar -zxf neo4j-1.2-unix.tar.gz


3. 啟動它
Mac & Linux -
$> NEO4J_FOLDER/bin/neo4j start

Windows -
雙點兩下解壓縮目錄下的 NEO4J_FOLDER/bin/neo4j

4. 如果你想以服務的方式來啟動它 :
Mac & Linux
cd $NEO4j_FOLDER
sudo ./bin/neo4j install
service neo4j-server status
  #應該會顯示Neo4j Server目前沒有正在運行
service neo4j-server start

Windows
(1). 右鍵點選 NEO4J_FOLDER\bin\InstallNeo4j
(2). 選擇以 管理員(administrator) 身份執行
安裝Jruby
欲安裝Jruby,通常我們都會建議安裝RVM 來做版本之間的切換.
你可以透過下列指令來安裝.
bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )	

安裝完成之後記得修改你的 ~/.bash_profile 如下 :
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"  # This loads RVM into a shell session.

安裝Neo4j.rb
一旦rvm及Jruby安裝好後. 輸入
rvm use jruby
gem install neo4j
開始使用Neo4j.rb
要開始使用Neo4j.rb,首先我們得先瞭解Neo4j提供了三個主要部份.
一個部份是最基礎的呼叫JAVA API,那便是 Neo4j::NodeNeo4j::Relationship .
另一個部份是Ruby Class對應的JAVA API,那便是 Neo4j::NodeMixinNeo4j::RelationshipMixin .
第三個部份是給Rails或Sinatra使用的,那便是 Neo4j::Rails::ModelNeo4j::Rails::Relationship (作者努力中...).
第一個部份(Neoj4::Node),第二個部份(Neo4j::NodeMixin)與第三部份(Neo4j::Rails::Model)最大的差異就是 :
前兩者需要做 Transaction. 而後者是只有當物件被下了save指令,並通過驗證(validation)後才會才到資料庫.
資料型別
一般資料庫有資料型別,Neo4j也有自己的資料型別.
property :your_property_name, :type=>Type


如果不加 :type, 則預設並沒有資料型別. 聰明的Neo4j會自動判斷.
也就是,當我們存入比如 neoObject=123 則為Fixnum. neoObject="123" 則為String.
如果想設定資料型別,可使用的為 : Fixnum , Float , TrueClass , FalseClass , String ,Date ,DateTime
值得注意的是DateTime預設儲存為Java的long. 而這個可以在Neo4j::Config這個物件下做修改.
另外,我們還可使用Array當作資料型別來儲存上面的這些資料.
使用Array儲存資料時,必需注意 :
1. 所有的在Array的資料型別必需統一
2. Array一但被建立後便無法再做任何修改. 修改只能透過 刪除 並 重建 來達成.

除了上面這些,如果我們想要創建自己的property,比如把Ruby物件當作一種property,只要進到 Neo4j::Config 修改即可.

如果,這些資料型別都不符合我們的需求,我們也可以創建自己的型別.
class Foo
   include Neo4j::NodeMixin
   property :thing, :type => MyType
end

module Neo4j::TypeConverters
  class MyTypeConverter
    class << self
      def convert?(type)
        type == MyType
      end

      def to_java(val)
        "silly:#{val}"
      end

      def to_ruby(val)
        val.sub(/silly:/, '')
      end
    end
  end
end

定義節點
定義一個節點,就有點像是MySQL的定義一個Table一樣.
class Member
  include Neo4j::NodeMixin
  property :first_name, :type=>String
  property :last_name, :type=>String
end


一但完成定義後,我們便可以在程式內建立這個節點,比如 :
Member.new(:first_name=>"Ample",:last_name=>"Ex")


值得注意的是,所有任何與Neo4j資料庫讀取,寫入相關的動作,都必需在
Neo4j::Transaction.run do
  
end

之間完成. 由於只有當Transaction結束時,才會做寫入的動作,在Transaction之前,都是暫存於記憶體內.
所以,如果我們在這裡面寫了10000筆資料,而不做Transaction,那麼速度就會越來越慢.
節點屬性
節點除了資料型別的定義,還可以設定其他許多有趣的東西. 比如
1. 定義index來讓Lucene搜尋.
class Member
	include Neo4j::NodeMixin
	property :first_name
	index :first_name ,:type=> :fulltext
end


如上,除了我們原本熟悉的節點定義方式,還增加了index這個東西.
增加了這個屬性為的是能讓Lucene 透過像下面範例的方式找到節點.

2. 定義Lecene搜尋方式.
:type 則為搜尋的方式. 預設為:exact (完全精準比對). 而你可以設為:fulltext (全文搜尋).
所以,假設我們有五筆會員資料,而 first_name 分別為 : Amp , Ample , Cool Ample , Ampless , pels .
Member.find(:first_name=>"Amp",:type=>:fulltext)


則結果為 : Amp , Ample , Cool Ample , Ampless
如果我們把 fulltext 改成 exact (或直接移除:type) ,則 結果 只會剩 : Amp

3. 定義共用Inex.
何謂共用定義節點,就是我們只要搜尋一次,就可以在兩個節點的所有資料內找到符合的結果.
這樣講非常抽像. 我們看範例 :
class Member
	include Neo4j::NodeMixin
  	property :member_id
  	node_indexer Employee
  	node_indexer Boss
	index :member_id
end

class Employee
	blablabla
end

class Boss
	blablabla
end


就如同上例,我們在Member裡下了一個node_indexer. 意思就是和Employee共用 member_id這個property.
這種設計方式通常在於比如員工老闆 在系統裡都有共通的資料,可能是姓名,電話.
這個時候我們就只要建立一次Member節點,然後分享給Boss和Employee,其他額外的資料屬性再由Boss和Employee自行定義.
而,當我們使用 Boss.find(:member_id=>x) 時,一樣是可以找到的.
節點關係
節點跟節點可以有一種關係,十種,千種. 你喜歡多少就多少. 而這也是 圖形資料庫 的強項.
如何增加節點關係?
以上述的例子,假設我們建了一個Member節點. 那麼我們只要透過下列的方式就可以很簡單的建立關係 :
a=Member.new(:first_name=>"Amp")
b=Member.new(:first_name=>"Exe")
a.outgoing(:friendship) << b


在上面的例子裡我們可以看到,這是單向的關係. 這個單向是由a連到b. 所以當由a查尋時,會是由a出發的friendship. 而b則是進來的friendship.
以程式寫法,由a到b 以及 由b到a 的寫法如下 :
a.outgoing(:friendship).first   
b.incoming(:friendship).first


或是,你也可以反過來寫. 那麼上面的的寫法就會是

b.incoming(:friendship) << a

a.outgoing(:friendship).first
b.incoming(:friendship).first


我們也許會想問,那如果是複雜的關係又如何處理? 比如我要找 我朋友的女朋友們是哪些人.
我們以下面來寫個比較完整的範例讓大家瞭解.
class Member
include Neo4j::NodeMixin
property :name
index :name
end
me=Member.new(:name=>"Me")
daniel=Member.new(:name=>"Daniel")
david=Member.new(:name=>"David")
wang=Member.new(:name=>"Wang")
lisa=Member.new(:name=>"Lisa")
wendy=Member.new(:name=>"Wendy")
terisa=Member.new(:name=>"Terisa")
kristy=Member.new(:name=>"Kristy")

me.outgoing(:frienship) << daniel
me.outgoing(:friendship) << david
me.outoging(:friendship) << wang

daniel.outgoing(:datingship) << lisa
daniel.outgoing(:datingship) << wendy
daniel.outgoing(:datingship) << terisa

david.outgoing(:datingship) << kristy

wang.outgoing(:datingship) << lisa

me.outoging(:frienship).outgoing(:datingship)



如此,便可以撈出所有我朋友的女朋友了.
節點深度搜尋
我們已經學會了如何從一個節點透過一個某個關係來找到另一個節點.
但是有可能這個關係會有很多層,比如 朋友的朋友的朋友的朋友的......
如果我們只想找朋友的朋友呢?
a.outgoing(:friendship).depth(2)


.depth之中我們可以代入任何整數數字,亦或是改成:all 來做全部深度的搜尋.
如果我們不加入.depth , 則便是預設的一層.


簡單的條件過濾
也許這樣找出來的資料太多,我們想要篩選. 透過filter, prune我們可以很簡單的達到.
繼承上面的 朋友的女朋友例子 , 如果我們想找到只有好朋友David以及Daniel的女朋友,那麼我們該如何處理?
me.outgoing(:friendship).filter{|path|
	path.end_node.name=="David" || path.end_node.name=="Daniel"
}.outgoing(:datingship)


如此就可以抓出這兩個人的女朋友們了.
值得注意的是,filter裡所呈現的是path. 一個path會有起始點(start_node)也會有結束點(end_node).
使用filter它會將我們搜尋出來的結果每一個做比對. 如果filter block內的條件回傳為true,則該筆資料才被抓出.
與filter相反的是prune. prune很簡單就是block內的條件為false,則該筆資料才會被抓出.
如果以上面的例子以prune重寫. 那麼大概就是像 :
me.outgoing(:friendship).prune{|path|
	path.start_node.name!="David" && path.end_node.name!="Daniel"
}.outgoing(:datingship)


圖形搜尋在Neo4j可以說是精華,但這裡是基本的介紹. 也就不做太過深入的解說. 有興趣的請點我 看進階說明
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics