Hello World 之Spring Boot 調用圖數據庫Neo4j



   
   
  
  
          
  1. 明日歌
  2. [清]錢鶴灘
  3. 明日復明日,明日何其多!
  4. 我生待明日,萬事成蹉跎

1. 圖數據庫Neo4j之愛的初體驗 ----與君初相識,猶似故人歸

在如今大數據(big data)橫行的時代,傳統的關系型數據庫如oracle,mysql在大數據量,高並發的場景下顯得力不從心。於是乎,NoSQL橫空出世,如column-based的cassandra數據庫,document-based的MongoDB,還有今天介紹的小眾的graph-based的圖數據數據庫Neo4j。

圖數據庫名字的由來其實與其在底層的存儲方式有關,圖數據庫並不表示會存儲圖形,圖片等。Neo4j底層會以圖的方式把用戶定義的節點(nodes)以及關系(relationships)存儲起來,Nodes 和 Relationships 包含key/value形式的屬性。Nodes通過Relationships所定義的關系相連起來,形成關系型網絡結構。通過這種方式,可是高效的實現從某個節點開始,通過節點與節點間關系,找出兩個節點間的聯系。

2. Neo4j之愛的再判斷----天生我材必有用

以金庸先生的《神雕俠侶》為例,這里面的人物關系圖很復雜,神雕大俠楊過有很多粉絲,他的粉絲又有自己的粉絲(二度人脈),粉絲粉絲又有自己的粉絲……..假設楊大俠從南宋就開了個博客,到如今必定圈粉無數,如果要找到楊過的粉絲和他的六度七度人脈,運用傳統的關系型數據庫的話,則需要在關系表里存儲很多關系數據,成萬上億,百億,千億甚至更多。不論用關系型數據庫的分庫分表技術還是其他優化手段,在復雜度和性能方面都可能會遇到瓶頸。

而圖數據庫neo4j運用了圖的遍歷算法設計,即從一個節點開始,根據其連接的關系,可以快速和方便地找出它的鄰近節點,從而具有簡單的存儲方式和極高的查詢性能。

關於neo4j的更多細節和neo4j server的安裝以及用cypher語言創建節點,關系等內容可以參考網上資料(如:https://blog.csdn.net/victory0508/article/details/78414798),本文着重關注Spring boot 2.0 如何簡潔的調用neo4j.

3. Neo4j執Spring boot之手----窈窕淑女,Spring boot好逑

在我的第一篇博客里介紹了Spring boot 2.0。本文將Spring boot 結合Spring Data,用極少的代碼,基本零配置,不用書寫任何查詢(queries)語句(這里是cypher)實現了Neo4j的增刪改查。

3.1 Neo4j的連接配置

Spring boot的配置文件默認在src/main/resources下面,支持傳統的application.properties 和application.yml

application.properties版:


   
   
  
  
          
  1. spring.data.neo4j.username=neo4j
  2. spring.data.neo4j.password=helloworld

application.yml版:      


   
   
  
  
          
  1. spring:
  2. data:
  3. neo4j:
  4. username: neo4j
  5. password: helloworld

3.2 實體類(model 


   
   
  
  
          
  1. @NodeEntity
  2. public class Legend {
  3. @Id @GeneratedValue private Long id;
  4. private String name;
  5. private Legend() {
  6. // Empty constructor required as of Neo4j API 2.0.5
  7. };
  8. public Legend(String name) {
  9. this.name = name;
  10. }
  11. /**
  12. * Neo4j doesn't REALLY have bi-directional relationships. It just means when querying
  13. * to ignore the direction of the relationship.
  14. * https://dzone.com/articles/modelling-data-neo4j
  15. */
  16. @Relationship(type = "FANS", direction = Relationship.UNDIRECTED)
  17. public Set<Legend> fans;
  18. public void fansWith(Legend legend) {
  19. if (fans == null) {
  20. fans = new HashSet<>();
  21. }
  22. fans.add(legend);
  23. }
  24. public String toString() {
  25. //java 8 stream and optional
  26. return this.name + "'s fans => "
  27. + Optional.ofNullable( this.fans).orElse(
  28. Collections.emptySet()).stream()
  29. .map(Legend::getName)
  30. .collect(Collectors.toList());
  31. }
  32. public String getName() {
  33. return name;
  34. }
  35. public void setName(String name) {
  36. this.name = name;
  37. }
  38. }

實體類annotated by 注解@NodeEntity,這樣當調用保存這個實體時(save方法),會將它保存到neo4j數據庫。

另一個重要的部分是

 @Relationship(type = "FANS", direction = Relationship.UNDIRECTED)
  
  
 
 
         

用來建立關系,UNDIRECTED表示忽略關系的方向性。

應用程序通過調用fansWith方法,可以將神雕的人物們聯系起來。

3.3 Spring data neo4j

        Spring Data  屬於Spring 大家庭,用於簡化對數據庫的訪問,在很多情況下,甚至都不用寫任何queries就可以實現對數據庫的各種操作。 


   
   
  
  
          
  1. import org.springframework.data.repository.CrudRepository;
  2. public interface LegendRepo extends CrudRepository<Legend, Long> {
  3. Legend findByName(String name);
  4. }

 CrudRepository 是關鍵,它封裝常用的如保存,更新等操作。

上面的findByName方法表示用name來查詢。name必須是實體類的一個屬性。在關系型數據庫里,spring data會自己將他轉化成 select * from table where name=?。而neo4j使用cypher語言,類似轉化成查詢語句


   
   
  
  
          
  1. MATCH (n:`Legend`) WHERE n.`name` = { `name_0` } WITH n RETURN n,
  2. [ [ (n)-[r_f1:`FANS`]-(l1:`Legend`) | [ r_f1, l1 ] ] ], ID(n) with params {name_0=楊過}

如果要表達Or或者And關系(假設legend有屬性level),方法名將會是

findByNameAndLevel(String name,String level)

如果要分頁,需要繼承PagingAndSortingRepository,而不是CrudRepository 。有關springdata的更多細節,筆者將會在以后的博客中詳細介紹。

3.4 Spring boot 啟動類 


   
   
  
  
          
  1. @SpringBootApplication
  2. @EnableNeo4jRepositories
  3. public class SpringBootNeo4jApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(SpringBootNeo4jApplication.class, args);
  6. }
  7. }

這里的注解@EnableNeo4jRepositories告訴spring boot程序使用neo4j repository。

3.5 Spring boot 測試類 

 開發工具Spring tool suites自動會生成測試類,添加自己的邏輯代碼,保存三個節點:楊過,小龍女和郭襄。

然后建立她們之間的關系,小龍女和郭襄均是楊過的粉絲。最后查詢出楊過的粉絲。


   
   
  
  
          
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class SpringBootNeo4jApplicationTests {
  4. @Autowired
  5. LegendRepo legendRepo;
  6. private final static Logger log = LoggerFactory.getLogger(SpringBootNeo4jApplicationTests.class);
  7. @Test
  8. public void contextLoads() {
  9. legendRepo.deleteAll();
  10. Legend yangguo = new Legend( "楊過");
  11. Legend dragonGirl = new Legend( "小龍女");
  12. Legend guoxiang = new Legend( "郭襄");
  13. List<Legend> team = Arrays.asList(yangguo, dragonGirl, guoxiang);
  14. log.info( "Before linking up with Neo4j...");
  15. //java 8 stream
  16. team.stream().forEach(legend -> log.info( "\t" + legend.toString()));
  17. legendRepo.save(yangguo);
  18. legendRepo.save(dragonGirl);
  19. legendRepo.save(guoxiang);
  20. yangguo = legendRepo.findByName(yangguo.getName());
  21. yangguo.fansWith(dragonGirl);
  22. yangguo.fansWith(guoxiang);
  23. legendRepo.save(yangguo);
  24. dragonGirl = legendRepo.findByName(dragonGirl.getName());
  25. dragonGirl.fansWith(guoxiang);
  26. // We already know that dragonGirl is a fan of yangguo
  27. legendRepo.save(dragonGirl);
  28. // We already know guoxiang fans with yangguo and dragongirl
  29. log.info( "Look up yangguo's fans ...");
  30. log.info(legendRepo.findByName( "楊過").toString());
  31. }
  32. }

運行代碼查看日志:

Look up yangguo's fans ...
Request: MATCH (n:`Legend`) WHERE n.`name` = { `name_0` } WITH n RETURN n,[ [ (n)-[r_f1:`FANS`]-(l1:`Legend`) | [ r_f1, l1 ] ] ], ID(n) with params {name_0=楊過}
 楊過's fans => [郭襄, 小龍女]
4. Neo4j 與Spring boot ----一生一代一雙人

Neo4j在某些場合能發揮自己的優勢,而用spring boot的方式,使得neo4j的使用非常簡單,自從有了spring boot,生活變得好輕松。

關注spring boot,請繼續關注我的博客。


原文地址:https://blog.csdn.net/weixin_41897365/article/details/79835319


免責聲明!

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



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