日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
為什么你應(yīng)該在你下個(gè)RubyAPP中使用Neo4j

每天,我都需要儲(chǔ)存大量的數(shù)據(jù),而我可以使用很多工具,比如 PostgreSQL,MySQL,SQLite,Redis 和 MongoDB,當(dāng)我積累了豐富的經(jīng)驗(yàn),并且熟練掌握這些工具的時(shí)候,我就不認(rèn)為他們還有什么樂(lè)趣了。我從心里熱愛(ài) Ruby,是因?yàn)樗苡腥げ⑶夷茏屛夷苡米约旱姆绞阶鲆恍┖軈柡Φ氖虑椤5俏也](méi)有意識(shí)到這樣的數(shù)據(jù)處理工具將會(huì)影響我很久,盡管它令我找到了新的樂(lè) 趣,所以請(qǐng)讓我向你介紹 Neo4j 吧。

什么是 Neo4j?

Neo4j 是圖形化的數(shù)據(jù)庫(kù)!這意味著它被優(yōu)化用于管理和查詢(xún)實(shí)體(節(jié)點(diǎn))之間的關(guān)系(節(jié)點(diǎn)),而不是像一個(gè)使用表的關(guān)系數(shù)據(jù)庫(kù)那樣的東西。

為什么這很棒?想象一個(gè)沒(méi)有國(guó)外鑰匙的世界。數(shù)據(jù)庫(kù)中的每個(gè)實(shí)體的關(guān)系之間都十分密切,以至于可以直接引用其他實(shí)體。如果你想要引用的關(guān)系沒(méi)有關(guān)系 表或者搜索掃面,就只需要幾個(gè)鏈接就行了。這***的展現(xiàn)了典型的對(duì)象模型。這非常令人興奮,因?yàn)?Neo4j 可以提供很多我們所期待的數(shù)據(jù)庫(kù)應(yīng)該具有的功能,并且為我們提供了工具來(lái)查詢(xún)復(fù)雜數(shù)據(jù)圖形。

介紹 ActiceNote

為了鏈接 Neo4j,我們將使用 neo4j gem。連接到你在 Rails 應(yīng)用程序中的 Neo4j 的方法,可以在 gem  文檔中找到。同時(shí)此顯示代碼的應(yīng)用程序也可在 GitHub 庫(kù)中運(yùn)行 Rails 應(yīng)用程序(使用 sitepoint 的分支)你可以在你的數(shù)據(jù)庫(kù)中運(yùn)行使用前 rake load_sample_data 命令來(lái)填充數(shù)據(jù)庫(kù)。

下面是一個(gè)關(guān)于資產(chǎn)模型的基本案例來(lái)源于資產(chǎn)管理的Rails APP

 
 
  1. class Asset 
  2.   include Neo4j::ActiveNode 
  3.  
  4.   property :title 
  5.  
  6.   has_many :out, :categories, type: :HAS_CATEGORY 
  7. end 

簡(jiǎn)單解釋一下:

1.Neo4j的GEM給我們的Neo4j:: ActiveNode模塊,其中包括我們所做的這個(gè)模型

2.此資產(chǎn)意味著這種模式將負(fù)責(zé)所有在Neo4j標(biāo)記資產(chǎn)的節(jié)點(diǎn)(除標(biāo)簽一個(gè)節(jié)點(diǎn)可以有很多的標(biāo)簽發(fā)揮類(lèi)似的作用)

3.我們有一個(gè)title屬性來(lái)描述各個(gè)節(jié)點(diǎn)

4.我們有傳出has_many的分類(lèi)關(guān)聯(lián)。這種關(guān)聯(lián)幫助我們通過(guò)下面的數(shù)據(jù)庫(kù)HAS_CATEGORY關(guān)系找到分類(lèi)的對(duì)象。

有了這個(gè)模型,我們可以進(jìn)行基本的查詢(xún)來(lái)找到一個(gè)資產(chǎn),并得到它的分類(lèi)

 
 
  1. 2.2.0 :001 > asset = Asset.first 
  2.  => # 
  3. 2.2.0 :002 > asset.categories.to_a 
  4.  => [#

熟悉 ActiveRecord 或者 Mongoid 的任何人會(huì)看到找個(gè)上百次。為了讓它變得更有趣,讓我們來(lái)定義一個(gè) Category 模型:

 
 
  1. class Category 
  2.   include Neo4j::ActiveNode 
  3.  
  4.   property :name 
  5.  
  6.   has_many :in, :assets, origin: :categories 
  7. end 

在這里,我們的關(guān)聯(lián)有一個(gè) origin 的選項(xiàng)引用了 資產(chǎn)(asset)模型的 categories 關(guān)聯(lián)。如果我們想要的話,我們可以再一次指定 type: :HAS_CATEGORY

創(chuàng)建Recommendations

如果我們想要獲得所有和我們的 資產(chǎn)共享一個(gè) category 的所有 資產(chǎn)(asset)會(huì)怎樣?

  
 
  1. 2.2.0 :003 > asset.categories.assets.to_a 
  2.  => [#, ...] 

那這樣又會(huì)發(fā)生什么事?ActiveNode 生成一個(gè)數(shù)據(jù)庫(kù)查詢(xún),指定了一個(gè)從我們的 資產(chǎn)(asset)到所有其他共享一個(gè) category 的 資產(chǎn)(asset)的路徑。然后數(shù)據(jù)庫(kù)會(huì)發(fā)回那些 資產(chǎn)(asset)給我們。下面給出它用到的查詢(xún):

 
 
  1. MATCH 
  2.   asset436, asset436-[rel1:`HAS_CATEGORY`]->(node3:`Category`), 
  3.   node3<-[rel2:`HAS_CATEGORY`]-(result_assets:`Asset`) 
  4. WHERE (ID(asset436) = {ID_asset436}) 
  5. RETURN result_assets 
  6.  
  7. Parameters: {ID_asset436: 436} 

這種查詢(xún)語(yǔ)言叫做 Cypher,它等同于 Neo4j 的 SQL。特別注意括號(hào)周?chē)?jié)點(diǎn)和接頭的 ASCII 風(fēng)格所代表的關(guān)系。這種 Cypher 查詢(xún)有點(diǎn)冗余,因?yàn)?ActiveNode 在算法上面會(huì)生成這些查詢(xún)。如果一個(gè)人去寫(xiě)這種查詢(xún),它將會(huì)看起來(lái)像這樣:

 
 
  1. MATCH source_asset-[:HAS_CATEGORY]->(:Category)<-[:HAS_CATEGORY]-(result_assets:Asset) 
  2. WHERE ID(source_asset) = {source_asset_id} 
  3. RETURN result_assets 
  4.  
  5. Parameters: {source_asset_id: 436} 

同時(shí),我也發(fā)現(xiàn) Cypher 比 SQL 要容易并且更強(qiáng)大, 但是我們?cè)谶@里我們不會(huì)擔(dān)心 Cypher 太多。如果你之后想學(xué)習(xí)更過(guò)關(guān)于 Cypher 的知識(shí),你可以查找 totorials 和 refcard。

正如你所看到的,我們可以使用 Neo4j 來(lái)跨實(shí)體。太了不起了!我們也可以使用帶有成對(duì) JOINS 的 SQL 來(lái)做到。雖然 Cypher 看起來(lái)很酷,但是我們還沒(méi)有什么重大的突破。假設(shè)我們想要使用這些查詢(xún)來(lái)創(chuàng)建一些基于共享 category 的 asset recommendation 會(huì)怎樣?我們會(huì)想要去對(duì) asset 排序然后按照最多共同 category 來(lái)排序。讓我們?cè)谖覀兊哪P椭袆?chuàng)建一個(gè)方法:

 
 
  1. class Asset 
  2.   ... 
  3.  
  4.   Recommendation = Struct.new(:asset, :categories, :score) 
  5.  
  6.   def asset_recommendations_by_category(common_links_required = 3) 
  7.     categories(:c) 
  8.       .assets(:asset) 
  9.       .order('count(c) DESC') 
  10.       .pluck('asset, collect(c), count(c)').reject do |_, _, count| 
  11.       count < common_links_required 
  12.     end.map do |other_asset, categories, count| 
  13.       Recommendation.new(other_asset, categories, count) 
  14.     end 
  15.   end 
  16. end 

這里有幾個(gè)有趣的地方值得注意一下:

  • 我們定義變量作為后續(xù)使用鏈的一部分(c 或者 asset)

  • 我們使用 Cypher 的 collect 函數(shù)來(lái)給我們一個(gè)包含一個(gè)共享 category 數(shù)組的結(jié)果列(參考下面的表)。還要注意,我們得到了完整的對(duì)象,不僅僅是列/屬性:

asset

collect(c)

count(c)

#

[#]

1

#

[#, #, …]

4

#

[#, #]

2

你注意到這里沒(méi)有一個(gè) GROUP BY 字句了嗎?Neo4j 非常智能地意識(shí)到 collect 和 count 是聚合函數(shù),并且在我們的結(jié)果中通過(guò)非聚合列排序(在這個(gè)案例中只有 asset變量)。

注意那條 SQL!

作為***一步,我們能夠創(chuàng)建的不僅僅是相同 category 的 recommendation。想象一下我們有下面 Neo4j 子圖:

除了共享的 category 之外,讓我們來(lái)解釋一下 creators 和 viewers asset 有多少共同之處:

 
 
  1. class Asset 
  2.   ... 
  3.   Recommendation = Struct.new(:asset, :score) 
  4.  
  5.   def secret_sauce_recommendations 
  6.     query_as(:source) 
  7.       .match('source-[:HAS_CATEGORY]->(category:Category)<-[:HAS_CATEGORY]-(asset:Asset)').break 
  8.       .optional_match('source<-[:CREATED]-(creator:User)-[:CREATED]->asset').break 
  9.       .optional_match('source<-[:VIEWED]-(viewer:User)-[:VIEWED]->asset') 
  10.       .limit(5) 
  11.       .order('score DESC') 
  12.       .pluck( 
  13.         :asset, 
  14.         '(count(category) * 2) + (count(creator) * 4) + (count(viewer) * 0.1) AS score').map do |other_asset, score| 
  15.       Recommendation.new(other_asset, score) 
  16.     end 
  17.   end 
  18. end 

在這里我們深入研究并開(kāi)始構(gòu)建我們自己的查詢(xún)。結(jié)構(gòu)一樣,但不僅僅是通過(guò)在共享 category 的兩個(gè) asset 之間查找一條path, 我們也會(huì)指定兩個(gè)更多的可選path。我們可以指定三個(gè)可選path,但是 Neo4j 需要使用數(shù)據(jù)庫(kù)里邊每一個(gè)其他的 資產(chǎn)(asset) 來(lái)對(duì)比我們的 資產(chǎn)(asset)。為我們的 category 節(jié)點(diǎn)使用 match 而不是 optional_match,我們要求至少有一個(gè)共享 category。這樣極大的限制了我們的搜索空間。

在圖中有1個(gè)共享 category,0個(gè)共享 creator 以及兩個(gè)共享的 viewer。這意味著”Ruby“和”Ruby on Rails“之間的分?jǐn)?shù)將會(huì)是:

(1*2) + (0*4) + (2*0.1) =2.2

還要注意,我們?cè)谶@三條path上的 count 聚合函數(shù)上做計(jì)算(和排序)。對(duì)我來(lái)說(shuō)很酷,它使得我有點(diǎn)興奮地去思考。。。

容易授權(quán)

讓我們來(lái)處理另外一個(gè)普遍的問(wèn)題。假設(shè)你的 CEO 來(lái)到你桌子前對(duì)你說(shuō),“我們已經(jīng)構(gòu)建了一個(gè)非常棒的 app,但是客戶(hù)想要能夠控制誰(shuí)可以看他們的東西。你可以建立一些隱私控制嗎?”看起來(lái)很簡(jiǎn)單。讓我們依賴(lài)一個(gè)標(biāo)記來(lái)訪問(wèn)私有資產(chǎn)(asset):

 
 
  1. class Asset 
  2.   ... 
  3.   property :public, default: true 
  4.  
  5.   def self.visible_to(user) 
  6.     query_as(:asset) 
  7.       .match_nodes(user: user) 
  8.       .where("asset.public OR asset<-[:CREATED]-user") 
  9.       .pluck(:asset) 
  10.   end 
  11. end 

使用這些設(shè)計(jì),你可以顯示用戶(hù)可以看到的所有資產(chǎn)(asset),因?yàn)橘Y產(chǎn)(asset)是公開(kāi)的或者因?yàn)橛^察者擁有它。沒(méi)問(wèn)題,但同樣不是個(gè)大問(wèn)題。在另外一個(gè)數(shù)據(jù)庫(kù)里邊,你可以在兩個(gè)列/屬性上面做搜索。讓我們來(lái)感受一下!

產(chǎn)品經(jīng)理來(lái)到你身邊說(shuō),“嘿,謝謝你,但是現(xiàn)在人們想要給其他用戶(hù)直接訪問(wèn)他們私有的東西”。沒(méi)問(wèn)題!你可以創(chuàng)建以個(gè) UI 來(lái)讓用戶(hù)添加和移除他們資產(chǎn)(asset)的 VIEWALBE_BY 關(guān)系,并且可以這樣查詢(xún):

 
 
  1. class Asset 
  2.   ... 
  3.  
  4.   def self.visible_to(user) 
  5.     query_as(:asset) 
  6.       .match_nodes(user: user) 
  7.       .where("asset.public OR asset<-[:CREATED]-user OR asset-[:VIEWABLE_BY]->user") 
  8.       .pluck(:asset) 
  9.   end 
  10. end 

另外這將是一個(gè)連接表。你仍在用戶(hù)可以獲取資產(chǎn)(asset)的另外一個(gè)路徑。花費(fèi)一些時(shí)間來(lái)欣賞 Neo4j 無(wú)模式的本質(zhì)。

滿足于你的工作日,靠在椅子上和喝著下午茶。當(dāng)然,前提是社交媒體客戶(hù)服務(wù)代表說(shuō)“用戶(hù)喜歡新的功能,但是他們希望能夠創(chuàng)建分組以及分配訪問(wèn)分組。 你可以做到嗎?并且,能允許任意層次的分組嗎?你深深得看著他們的眼睛幾分鐘,然后說(shuō):”當(dāng)然!“。之后開(kāi)始變得復(fù)雜,來(lái)看個(gè)例子:

如果這些資產(chǎn)都是私人代碼,到目前為止給 Matz 和 tenderlove 去訪問(wèn) Ruby,以及 DHH 去訪問(wèn) Ruby on Rails。添加分組支持,你開(kāi)始直接分配分組:

 
 
  1. class Asset 
  2.   ... 
  3.  
  4.   def self.visible_to(user) 
  5.     query_as(:asset) 
  6.       .match_nodes(user: user) 
  7.       .where("asset.public 
  8.  OR asset<-[:CREATED]-user OR asset-[:VIEWABLE_BY]->user OR  
  9. asset-[:VIEWABLE_BY]->(:Group)<-[:BELONGS_TO]-user") 
  10.       .pluck('DISTINCT asset') 
  11.   end 
  12. end 

這個(gè)是很簡(jiǎn)單的,因?yàn)槟阒恍枰砑恿硗庖粭l路徑。當(dāng)然,到目前為止那是我們的舊帽子。 Tenderlove 和 Yehuda 就能夠看到”Ruby on Rails“資源(asset),因?yàn)樗麄兪恰癛ailsists”分組的。還要注意:現(xiàn)在一些用戶(hù)有多個(gè)資產(chǎn)(asset)路徑(像 Matz 去 Ruby 通過(guò) Rubyists 分組和通過(guò) CREATED 關(guān)聯(lián))你需要返回 DISTINCT asset。

然而通過(guò)一個(gè)層次結(jié)構(gòu)組織來(lái)指定一個(gè)任意的path需要花費(fèi)你較多的時(shí)間。你可以查看Neo4j文檔直到你找到一些叫做”variable relationships“的東西并試試:

 
 
  1. class Asset 
  2.   ... 
  3.  
  4.   def self.visible_to(user) 
  5.     query_as(:asset) 
  6.       .match_nodes(user: user) 
  7.       .where("asset.public OR asset<-[:CREATED]-user OR asset-[:VIEWABLE_BY] 
  8.       ->user OR asset-[:VIEWABLE_BY]->(:Group)<-[:HAS_SUBGROUP*0..5]-(:Group)<-[:BELONGS_TO]-user") 
  9.       .pluck('DISTINCT asset') 
  10.   end 
  11. end 

這里你已經(jīng)做到了!這種查詢(xún)會(huì)找到可訪問(wèn)一個(gè) group 的 資產(chǎn)(asset)并且貫穿了0到5的 HAS_SUBGROUP關(guān)系,***以一個(gè)查看用戶(hù)是否在***一個(gè) group 里邊的檢查結(jié)束。你是這個(gè)故事的男主角,你的公司會(huì)為你能夠快速做好這項(xiàng)工作而給你獎(jiǎng)金。

結(jié)論

你可以用 Neo4j 做很多我做不到并且很棒的事情(包括使用它的 amazing web interface 去利用 Cyper 查找你的數(shù)據(jù))。它不僅僅是一種杰出的方式用一個(gè)簡(jiǎn)單而直觀的方式來(lái)存儲(chǔ)你的數(shù)據(jù),而且提供了很多高度聯(lián)系的數(shù)據(jù)查詢(xún)效率的好處(相信我你的數(shù)據(jù)是高度聯(lián)系的,盡管你沒(méi)有意識(shí)到)。我鼓勵(lì)你去看看 Neo4j 并在你的下一個(gè)項(xiàng)目中試試。


網(wǎng)頁(yè)題目:為什么你應(yīng)該在你下個(gè)RubyAPP中使用Neo4j
網(wǎng)頁(yè)路徑:http://www.dlmjj.cn/article/dpsjogc.html