利用Spring Data Neo4j搭建推薦系統


摘要:Neo4j是一款非常流行的開源圖型NoSQL數據庫。它完全支持ACID數據庫事務屬性,由於其良好的圖數據模型設計,Neo4j的速度非常快。對於構建性能優異的推薦系統來說,Neo4j的速度要比傳統的關系型數據庫快1000倍。

本文作者Daniel Bartl是一位項目開發者,在這里分享如何使用Spring Data Neo4j來構建推薦系統。Neo4j是一款非常流行的開源圖型NoSQL數據庫。它完全支持ACID數據庫事務屬性,由於其良好的圖形數據模型設計,Neo4j的速度非常快。對於連接的數據操作,Neo4j的速度要比傳統的關系型數據庫快1000倍。Spring DataSpring的一個核心項目,其下涵蓋了如Spring Data JPASpring Data MongoDBSpring Data RedisSpring for Hadoop等子項目,而Spring Data Neo4j也是Spring Data下的一個重要子項目,它提供了高級的特性以將注解的實體類映射到Neo4j圖型數據庫上。其模板編程模型類似於我們熟知的Spring模板,為與圖的交互提供了基礎,此外也用於高級的倉庫支持。該項目旨在為NoSQL數據庫操作提供便捷的支持。

在文章的末尾實現了一個的示例,該示例是一個購物系統,能計算出其他用戶的瀏覽結果供當前用戶參考是很重要的特性,現在很多電商都提供了這個特性,例如Amazon。由於用戶與商品之間的聯系是很容易使用圖表來表達的,因此該示例將使用Neo4j來表示結點以及結點之間的關系。

Spring Data Neo4j簡介

首先來介紹一下Spring Data。這是SpringSource的一個項目,旨在為NoSQL數據庫提供Spring的編程模型以及便捷性。Spring Data支持各種NoSQL數據庫,如Redis、Riak以及MongoDB等等。它還為Hadoop等MapReduce實現提供了一個抽象層。

Spring Data Neo4j起步於2010年,你可以在Neo4j網站上找到很多有價值的資源。目前最棒的指南就是由該項目的主開發者Michael Hunger所編寫的“Good Relationships”,這本指南提供了免費的下載,也有相應的HTML版本。其中有些Spring Data Neo4j代碼示例位於Spring Data Neo4j Git倉庫上。此外,O’Reilly也有一本關於Spring Data Neo4j的圖書

為何不使用核心Neo4j?

當然了,你也可以只使用核心Neo4j或是構建自己的集成方案。但如果你過去曾有過其他的Spring項目開發經驗,那么你就會發現Spring的好處了。作為一名軟件工程師,你不想關注於實體映射或是事務管理等細節信息。你只要了解這些概念就行了,剩下的事情Spring會幫你處理,這相當於Spring中的Hibernate支持一樣:

 

  • 通用的Spring與Spring Data基礎設施。你可以輕松將Neo4j嵌入到Spring框架所管理的現有應用當中。
  • 通過注解來聲明結點以及結點之間的關系。
  • 代碼很容易理解。
  • 實體狀態由圖型數據庫所維護。
  • 支持Neo4j服務器。

 

如何使用Spring Data Neo4j?

如果使用Maven,那么你可以通過將如下配置添加到pom.xml中,將Spring Data Neo4j引入到項目中(除了Spring與Neo4j的依賴外):

 

  • 通用的Spring與Spring Data基礎設施。你可以輕松將Neo4j嵌入到Spring框架所管理的現有應用當中。
  • 通過注解來聲明結點以及結點之間的關系。
  • 代碼很容易理解。
  • 實體狀態由圖型數據庫所維護。
  • 支持Neo4j服務器。

 

通過如下Spring的上下文來設置Neo4j:

Neo4j配置的“storeDirectory”屬性可以是任意的目錄,Neo4j數據庫將會存儲在那里。接下來開始實現代表圖模型的結點與關系實體。

如何聲明結點實體?

創建如下的類來表示結點實體:

在Spring框架中getters與setters對於屬性訪問是必須的。你還可以實現自己的額外的方法。一個典型的Neo4j實體一般是個經典的JavaBean,包含了屬性以及訪問器。此外,我們還建議實現equals與hashCode方法,因為有時Spring Data Neo4j會比較對象來判斷結點與關系映射。

如何創建結點與實體間的關系?

Spring Data可以通過3種不同的方式來處理結點間的關系,到底選擇哪一種取決於兩個方面:需要建模的關系類型(1對1還是1對多)以及是簡單關系還是復雜關系。復雜關系擁有額外的屬性。

1對1關系非常簡單:主結點通過屬性來引用子節點(需要實現訪問器),無需注解。Spring Data會處理所有其他事情。

在簡單的1對多關系中,你需要在主結點中添加一個包含子結點的集合(參見上述代碼示例)。除此之外,你還需要通過@RelatedTo(type = “relationshipType”) 對集合添加注解,如下所示:

復雜關系能夠展示出Spring Data強大的圖建模能力。你可以通過額外的屬性對真實世界的關系建模,為了做到這一點,你需要創建用於存儲關系屬性的關系實體。此外,還需要通過注解(@StartNode與@EndNode)來指定主結點和子結點。參加如下代碼示例:

要注意@Fetch屬性。在很多情況下,在加載完特定的實體后,並不是所有相關的1對多對象都需要加載出來。當加載了一個結點實體后,Spring Data的默認行為只是取得標識相關對象的ID列表。這種方式類似於Hibernate等框架的延遲加載機制。如果不希望這樣,那可以在相應的結點實體上添加@Fetch注解。

一般來說,將關系類型作為常量定義在單獨的類中是個好做法,因為這些字符串會用在不同類中的不同結點上。我們的圖模型在結點間存在兩種關系類型,因此這個類如下代碼所示:

 


如何加載實體及實體間的關系?

要想訪問實體與關系,我們需要創建自己的接口並繼承Spring的GraphRepository接口,如下代碼所示:

 

如你所見,這個圖倉庫是個接口,只定義了函數名、返回值與Cypher查詢(如果需要的話)。這非常方便,因為框架並不需要相應的實現。根據上面聲明的參數以及主接口“GraphRepository”,Spring Data可以創建出與Neo4j核心API交互的代理對象。要想了解更多細節信息,請參閱關於倉庫的文檔。如果不熟悉Cypher,那么請看看這個Cypher指南。然而,有時自己實現GraphRepository也是必要的,在這種情況下,你可以編寫一個類並繼承該接口。

Spring Data Neo4j有哪些限制?

 

  1. 現在,它無法運行同時包含DISTINCT與ORDER BY的Cypher查詢。
  2. 如果遇到問題,日志消息不太直觀。

 

關於示例

該示例展示了一個購物系統的圖倉庫部分,重點是獲得其他用戶也查看過的商品。比如說,如果瀏覽過“奶酪比薩”頁面的用戶也看過“培根披薩”頁面,那么這對於尋找“奶酪比薩”的用戶也會很有用。你可以在Spring Data Neo4j Product User Test class中找到一些測試用例。

如何運行示例?

要想運行示例,你需要先安裝好Maven。如果不熟悉Maven,那么可以閱讀這篇文章來了解Maven的使用。示例代碼位於github上,地址是https://github.com/comsysto/spring-data-neo4j-showcase

遇到問題怎么辦?

在准備這個示例時,我們遇到了一些挑戰,相信你可能也會遇到:

 

  • 小心索引。如果使用id,那么應該在代碼中將其聲明為唯一的。
  • 如果使用的關系有屬性,那么應該使用@RelatedToVia。
  • 初始化所有集合,比如說上述示例中使用的HashSet。
  • 不要將graphId作為ID。被刪除結點的graphId會被Neo4j重用,並且在刪除前一個后會用來表示另一個對象。
  • 對於關系的開始與結束結點使用@Fetch,否則在加載結點時是不會獲取他們的。
  • 不要修改getters與setters,因為他們會被框架用來保存值。
  • 使用簡單的語句來開始Cypher查詢,然后不斷擴展直到達到自己的目標。
  • 小心Cypher查詢中的字符串 轉義。Neo4j核心API中的字符串轉義與Spring Data的不同。

 

另外,你可以根據自己的需要擴展示例。比如說,可以向結點實體添加更多的屬性等。

原文:DZone                                                                                        (編譯/薛梁  責編/付江)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM