中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

為什么要在Ruby APP中使用Neo4j

發布時間:2021-09-18 16:54:59 來源:億速云 閱讀:98 作者:柒染 欄目:編程語言

為什么要在Ruby APP中使用Neo4j,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

每天,我都需要儲存大量的數據,而我可以使用很多工具,比如 PostgreSQL,MySQL,SQLite,Redis 和  MongoDB,當我積累了豐富的經驗,并且熟練掌握這些工具的時候,我就不認為他們還有什么樂趣了。我從心里熱愛  Ruby,是因為它很有趣并且能讓我能用自己的方式做一些很厲害的事情。但是我并沒有意識到這樣的數據處理工具將會影響我很久,盡管它令我找到了新的樂 趣,所以請讓我向你介紹 Neo4j 吧。

什么是 Neo4j?

Neo4j 是圖形化的數據庫!這意味著它被優化用于管理和查詢實體(節點)之間的關系(節點),而不是像一個使用表的關系數據庫那樣的東西。

為什么這很棒?想象一個沒有國外鑰匙的世界。數據庫中的每個實體的關系之間都十分密切,以至于可以直接引用其他實體。如果你想要引用的關系沒有關系 表或者搜索掃面,就只需要幾個鏈接就行了。這***的展現了典型的對象模型。這非常令人興奮,因為 Neo4j  可以提供很多我們所期待的數據庫應該具有的功能,并且為我們提供了工具來查詢復雜數據圖形。

介紹 ActiceNote

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

下面是一個關于資產模型的基本案例來源于資產管理的Rails APP

class Asset   include Neo4j::ActiveNode    property :title    has_many :out, :categories, type: :HAS_CATEGORY end

簡單解釋一下:

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

2.此資產意味著這種模式將負責所有在Neo4j標記資產的節點(除標簽一個節點可以有很多的標簽發揮類似的作用)

3.我們有一個title屬性來描述各個節點

4.我們有傳出has_many的分類關聯。這種關聯幫助我們通過下面的數據庫HAS_CATEGORY關系找到分類的對象。

有了這個模型,我們可以進行基本的查詢來找到一個資產,并得到它的分類

2.2.0 :001 > asset = Asset.first  => #<Asset uuid: "0098d2b7-a577-407a-a9f2-7ec4153cfa60", title: "ICC World Cup 2015 "> 2.2.0 :002 > asset.categories.to_a  => [#<Category uuid: "91cd5369-605c-4aff-aad1-b51d8aa9b5f3", name: "Classification">]

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

class Category   include Neo4j::ActiveNode    property :name    has_many :in, :assets, origin: :categories end

在這里,我們的關聯有一個 origin 的選項引用了 資產(asset)模型的 categories 關聯。如果我們想要的話,我們可以再一次指定 type: :HAS_CATEGORY

創建Recommendations

如果我們想要獲得所有和我們的 資產共享一個 category 的所有 資產(asset)會怎樣?

2.2.0 :003 > asset.categories.assets.to_a  => [#<Asset uuid: "d2ef17b5-4dbf-4a99-b814-dee2e96d4a09", title: "WineGraph">, ...]

那這樣又會發生什么事?ActiveNode 生成一個數據庫查詢,指定了一個從我們的 資產(asset)到所有其他共享一個 category 的 資產(asset)的路徑。然后數據庫會發回那些 資產(asset)給我們。下面給出它用到的查詢:

MATCH   asset436, asset436-[rel1:`HAS_CATEGORY`]->(node3:`Category`),   node3<-[rel2:`HAS_CATEGORY`]-(result_assets:`Asset`) WHERE (ID(asset436) = {ID_asset436}) RETURN result_assets  Parameters: {ID_asset436: 436}

這種查詢語言叫做 Cypher,它等同于 Neo4j 的 SQL。特別注意括號周圍節點和接頭的 ASCII 風格所代表的關系。這種 Cypher 查詢有點冗余,因為 ActiveNode 在算法上面會生成這些查詢。如果一個人去寫這種查詢,它將會看起來像這樣:

MATCH source_asset-[:HAS_CATEGORY]->(:Category)<-[:HAS_CATEGORY]-(result_assets:Asset) WHERE ID(source_asset) = {source_asset_id} RETURN result_assets  Parameters: {source_asset_id: 436}

同時,我也發現 Cypher 比 SQL 要容易并且更強大, 但是我們在這里我們不會擔心 Cypher 太多。如果你之后想學習更過關于 Cypher 的知識,你可以查找 totorials 和 refcard。

正如你所看到的,我們可以使用 Neo4j 來跨實體。太了不起了!我們也可以使用帶有成對 JOINS 的 SQL 來做到。雖然 Cypher  看起來很酷,但是我們還沒有什么重大的突破。假設我們想要使用這些查詢來創建一些基于共享 category 的 asset  recommendation 會怎樣?我們會想要去對 asset 排序然后按照最多共同 category  來排序。讓我們在我們的模型中創建一個方法:

class Asset   ...    Recommendation = Struct.new(:asset, :categories, :score)    def asset_recommendations_by_category(common_links_required = 3)     categories(:c)       .assets(:asset)       .order('count(c) DESC')       .pluck('asset, collect(c), count(c)').reject do |_, _, count|       count < common_links_required     end.map do |other_asset, categories, count|       Recommendation.new(other_asset, categories, count)     end   end end

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

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

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

asset

collect(c)

count(c)

#<Asset>

[#<Category>]

1

#<Asset>

[#<Category>, #<Category>, &hellip;]

4

#<Asset>

[#<Category>, #<Category>]

2

&hellip;

&hellip;

&hellip;

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

注意那條 SQL!

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

為什么要在Ruby APP中使用Neo4j

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

class Asset   ...   Recommendation = Struct.new(:asset, :score)    def secret_sauce_recommendations     query_as(:source)       .match('source-[:HAS_CATEGORY]->(category:Category)<-[:HAS_CATEGORY]-(asset:Asset)').break       .optional_match('source<-[:CREATED]-(creator:User)-[:CREATED]->asset').break       .optional_match('source<-[:VIEWED]-(viewer:User)-[:VIEWED]->asset')       .limit(5)       .order('score DESC')       .pluck(         :asset,         '(count(category) * 2) + (count(creator) * 4) + (count(viewer) * 0.1) AS score').map do |other_asset, score|       Recommendation.new(other_asset, score)     end   end end

在這里我們深入研究并開始構建我們自己的查詢。結構一樣,但不僅僅是通過在共享 category 的兩個 asset 之間查找一條path,  我們也會指定兩個更多的可選path。我們可以指定三個可選path,但是 Neo4j 需要使用數據庫里邊每一個其他的 資產(asset)  來對比我們的 資產(asset)。為我們的 category 節點使用 match 而不是 optional_match,我們要求至少有一個共享  category。這樣極大的限制了我們的搜索空間。

在圖中有1個共享 category,0個共享 creator 以及兩個共享的 viewer。這意味著”Ruby“和”Ruby on Rails“之間的分數將會是:

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

還要注意,我們在這三條path上的 count 聚合函數上做計算(和排序)。對我來說很酷,它使得我有點興奮地去思考。。。

容易授權

讓我們來處理另外一個普遍的問題。假設你的 CEO 來到你桌子前對你說,“我們已經構建了一個非常棒的 app,但是客戶想要能夠控制誰可以看他們的東西。你可以建立一些隱私控制嗎?”看起來很簡單。讓我們依賴一個標記來訪問私有資產(asset):

class Asset   ...   property :public, default: true    def self.visible_to(user)     query_as(:asset)       .match_nodes(user: user)       .where("asset.public OR asset<-[:CREATED]-user")       .pluck(:asset)   end end

使用這些設計,你可以顯示用戶可以看到的所有資產(asset),因為資產(asset)是公開的或者因為觀察者擁有它。沒問題,但同樣不是個大問題。在另外一個數據庫里邊,你可以在兩個列/屬性上面做搜索。讓我們來感受一下!

產品經理來到你身邊說,“嘿,謝謝你,但是現在人們想要給其他用戶直接訪問他們私有的東西”。沒問題!你可以創建以個 UI 來讓用戶添加和移除他們資產(asset)的 VIEWALBE_BY 關系,并且可以這樣查詢:

class Asset   ...    def self.visible_to(user)     query_as(:asset)       .match_nodes(user: user)       .where("asset.public OR asset<-[:CREATED]-user OR asset-[:VIEWABLE_BY]->user")       .pluck(:asset)   end end

另外這將是一個連接表。你仍在用戶可以獲取資產(asset)的另外一個路徑。花費一些時間來欣賞 Neo4j 無模式的本質。

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

為什么要在Ruby APP中使用Neo4j

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

class Asset   ...    def self.visible_to(user)     query_as(:asset)       .match_nodes(user: user)       .where("asset.public  OR asset<-[:CREATED]-user OR asset-[:VIEWABLE_BY]->user OR  asset-[:VIEWABLE_BY]->(:Group)<-[:BELONGS_TO]-user")       .pluck('DISTINCT asset')   end end

這個是很簡單的,因為你只需要添加另外一條路徑。當然,到目前為止那是我們的舊帽子。 Tenderlove 和 Yehuda  就能夠看到”Ruby on  Rails“資源(asset),因為他們是“Railsists”分組的。還要注意:現在一些用戶有多個資產(asset)路徑(像 Matz 去  Ruby 通過 Rubyists 分組和通過 CREATED 關聯)你需要返回 DISTINCT asset。

然而通過一個層次結構組織來指定一個任意的path需要花費你較多的時間。你可以查看Neo4j文檔直到你找到一些叫做”variable relationships“的東西并試試:

class Asset   ...    def self.visible_to(user)     query_as(:asset)       .match_nodes(user: user)       .where("asset.public OR asset<-[:CREATED]-user OR asset-[:VIEWABLE_BY]       ->user OR asset-[:VIEWABLE_BY]->(:Group)<-[:HAS_SUBGROUP*0..5]-(:Group)<-[:BELONGS_TO]-user")       .pluck('DISTINCT asset')   end end

這里你已經做到了!這種查詢會找到可訪問一個 group 的 資產(asset)并且貫穿了0到5的  HAS_SUBGROUP關系,***以一個查看用戶是否在***一個 group  里邊的檢查結束。你是這個故事的男主角,你的公司會為你能夠快速做好這項工作而給你獎金。


你可以用 Neo4j 做很多我做不到并且很棒的事情(包括使用它的 amazing web interface 去利用 Cyper 查找你的數據)。它不僅僅是一種杰出的方式用一個簡單而直觀的方式來存儲你的數據,而且提供了很多高度聯系的數據查詢效率的好處(相信我你的數據是高度聯系的,盡管你沒有意識到)。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兰考县| 石柱| 玉龙| 亚东县| 铜梁县| 浠水县| 恩施市| 根河市| 伊吾县| 栾川县| 余庆县| 临海市| 邯郸市| 梅州市| 泸西县| 武清区| 宜阳县| 新化县| 嵩明县| 柳林县| 资溪县| 罗山县| 淮滨县| 竹北市| 青河县| 崇信县| 思茅市| 甘孜县| 东安县| 石家庄市| 杭锦后旗| 靖远县| 观塘区| 织金县| 赣州市| 陈巴尔虎旗| 房产| 庆云县| 西吉县| 资兴市| 邵阳县|