Ruby中使用Neo4j——Neo4j.rb简介

阅读更多

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

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

 

安裝

  • Neo4j與Neo4j.rb的差別
  • 安裝Neo4j
  • 安裝jRuby
  • 安裝Neo4j.rb
  • 資料定義 與 型別

  • 資料型別
  • 定義節點
  • 節點屬性
  • 節點關係
  • 基本搜尋

  • 節點深度搜尋
  • 簡單的條件過濾
  • 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可以說是精華,但這裡是基本的介紹. 也就不做太過深入的解說. 有興趣的 請點我 看進階說明

    你可能感兴趣的:(Ruby中使用Neo4j——Neo4j.rb简介)