




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
PAGEPAGE172\o"第
15
章
Cypher查詢語言"Cypher查詢語言\o"第
4
章
在Java應用中使用Neo4j"在Java應用中使用Neo4j\o"第
9
章
在Python應用中使用Neo4j"在Python應用中使用Neo4j\o"第
5
章
Neo4j遠程客戶端庫"遠程客戶端訪問庫\o"第
8
章
多語言支持"多語言支持\o"第
17
章
Neo4j服務器"Neo4j服務器\o"第
18
章
RESTAPI"RESTAPI目錄前言I.簡介1.Neo4j的亮點2.圖數(shù)據(jù)庫概要3.Neo4j圖數(shù)據(jù)庫II.教程4.在Java應用中使用Neo4j5.Neo4j遠程客戶端庫6.遍歷查詢框架7.數(shù)據(jù)模型范例8.多語言支持9.在Python應用中使用Neo4j10.擴展Neo4j服務器III.參考11.性能12.事務管理13.數(shù)據(jù)導入14.索引15.Cypher查詢語言16.圖形算法17.Neo4j服務器18.RESTAPI19.在Python中使用Neo4j嵌入模式IV.操作20.安裝和部署21.配置和調優(yōu)22.高可用性模式23.備份24.安全25.監(jiān)視服務器V.工具集26.基于Web的Neo4j圖數(shù)據(jù)庫管理工具27.Neo4j命令行VI.社區(qū)28.社區(qū)支持29.促進Neo4j發(fā)展A.聯(lián)機幫助頁A.1.neo4jA.2.neo4j-shellA.3.neo4j-backupA.4.neo4j-coordinatorA.5.neo4j-coordinator-shellB.常見問題第1章Neo4j的亮點作為一款強健的,可伸縮的高性能數(shù)據(jù)庫,Neo4j最適合完整的企業(yè)部署或者用于一個輕量級項目中完整服務器的一個子集存在。它包括如下幾個顯著特點:完整的ACID支持高可用性輕易擴展到上億級別的節(jié)點和關系通過遍歷工具高速檢索數(shù)據(jù)適當?shù)腁CID操作是保證數(shù)據(jù)一致性的基礎。Neo4j確保了在一個事務里面的多個操作同時發(fā)生,保證數(shù)據(jù)一致性。不管是采用嵌入模式還是多服務器集群部署,都支持這一特性。更多詳細的介紹,請參考章節(jié):transactions??煽康膱D型存儲可以非常輕松的集成到任何一個應用中。隨著我們開發(fā)的應用在運營中不斷發(fā)展,性能問題肯定會逐步凸顯出來,而Neo4j不管應用如何變化,他只會受到計算機硬件性能的影響,不受業(yè)務本身的約束。部署一個neo4j服務器便可以承載上億級的節(jié)點和關系。當然,當單節(jié)點無法承載我們的數(shù)據(jù)需求時,我們可以進行分布式集群部署,詳細的細節(jié),請參考章節(jié):ha。將圖數(shù)據(jù)庫用于存儲關系復雜的數(shù)據(jù)是他最大的優(yōu)勢。通過Neo4j提供的遍歷工具,可以非常高效的進行數(shù)據(jù)檢索,每秒可以達到上億級的檢索量。一個檢索操作類似于RDBMS里面的連接(_join_)操作。第2章圖數(shù)據(jù)庫概要這個章節(jié)包括一個對圖數(shù)據(jù)模型的介紹以及將它與其他我們常見的數(shù)據(jù)持久化模型的比較。2.1.什么是圖數(shù)據(jù)庫?圖數(shù)據(jù)庫用圖來存儲數(shù)據(jù),是最接近高性能的一種用于存儲數(shù)據(jù)的數(shù)據(jù)結構方式之一。讓我們跟隨下面的圖表,用他們來解釋圖數(shù)據(jù)庫相關概念。我們將跟隨圖表中箭頭方向來讀懂圖想表達的真正含義。2.1.1.一個圖由無數(shù)的節(jié)點和關系組成“一張圖–數(shù)據(jù)記錄在→節(jié)點→包括的→屬性里面”最簡單的圖是單節(jié)點的,一個記錄,記錄了一些屬性。一個節(jié)點可以從單屬性開始,成長為成千上億,雖然會有一點點麻煩。從某種意義上講,將數(shù)據(jù)用關系連接起來分布到不同節(jié)點上才是有意義的。2.1.2.關系將圖各個部分組織起來“節(jié)點—被組織→關系—可以有→屬性”關系可以將節(jié)點組織成任意的結構,允許一張圖被組織成一個列表,一棵樹,一張地圖,或者一個復雜的實體–這個實體本身也是由復雜的,關系高度關聯(lián)的結構組成。2.1.3.用Traversal進行數(shù)據(jù)庫查詢“一個Traversal—導航→一張圖;他—標示→路徑—包含→節(jié)點”一次Traversal,你可以理解為是你通過一種算法,從一些開始節(jié)點開始查詢與其關聯(lián)的節(jié)點,比如你想找到“我朋友喜歡但我不喜歡的那首音樂是什么呢?”,又或者“如果斷電了,拿下服務器的服務會首影響?”等等問題。2.1.4.為節(jié)點和關系建立索引“一個索引—映射到→屬性—屬于→節(jié)點或者關系”經(jīng)常,你想通過某一給定的屬性值找到節(jié)點或者關系。比起通過遍歷我們的圖來書,用索引將會更加高效。比如“找到用戶名是tony的用戶”。2.1.5.Neo4j是一個圖數(shù)據(jù)庫“一個圖數(shù)據(jù)庫—管理→一張圖和與圖相關的→索引”Neo4j是一個有商業(yè)支持的開源圖數(shù)據(jù)庫。他被設計來用于拿下數(shù)據(jù)不斷高速成長的數(shù)據(jù)存儲,用高效的圖數(shù)據(jù)結構代替?zhèn)鹘y(tǒng)的表設計。用Neo4j工作,您的應用將得到圖的所有優(yōu)越表現(xiàn),以及您期望的高可靠性。2.2.比較各種數(shù)據(jù)庫模型圖數(shù)據(jù)庫通過在一張圖上存儲節(jié)點和關系來持久化我們的數(shù)據(jù)結構。比起其他持久化數(shù)據(jù)模型如何呢?因為圖是一種常規(guī)數(shù)據(jù)結構,讓我們與其他的進行一下比較試試看。2.2.1.從圖數(shù)據(jù)庫轉換成RDBMS將所有的數(shù)據(jù)用豎立的堆棧表示,并且保持他們直接的關系,你可以看到下面一張圖。一個RDBMS被優(yōu)化用于聚合數(shù)據(jù),而Neo4j擅長于高度關聯(lián)的數(shù)據(jù)。圖2.1.RDBMS圖2.2.用圖實現(xiàn)RDBMS模型2.2.2.從圖數(shù)據(jù)庫轉換成Key-Value數(shù)據(jù)庫Key-Value模型適合用于簡單的數(shù)據(jù)或者列表。當數(shù)據(jù)之間不斷交互關聯(lián)時,你更需要一張圖模型。Neo4j讓你能驚醒制作簡單的數(shù)據(jù)結構到復雜,互相連接的數(shù)據(jù)。圖2.3.Key-Value存儲模型K*代表一個鍵,V*代表一個值。請注意,某些鍵指向其他鍵以及普通值。圖2.4.用圖實現(xiàn)Key-Value模型2.2.3.從圖數(shù)據(jù)庫轉換成列數(shù)據(jù)庫列式(大表)數(shù)據(jù)庫是Key-Value模型的升級,用“”來允許行數(shù)據(jù)增加。如果存儲一張圖,這個表將是分層的,關系也是非常明確的。2.2.4.從圖數(shù)據(jù)庫轉換成文檔型數(shù)據(jù)庫文檔型數(shù)據(jù)庫用文檔進行層次劃分,而自由的數(shù)據(jù)規(guī)劃也很容易被表示成一顆樹。成長為一張圖的話,文檔之間的關聯(lián)你需要更有代表性的數(shù)據(jù)結構來存儲,而在Neo4j中,這些關系是非常容易處理的。圖2.5.文檔型數(shù)據(jù)庫D=文檔,S=子文檔,V=值,D2/S2=關聯(lián)到(其他)文檔的索引。圖2.6.從圖數(shù)據(jù)庫轉換成文檔型數(shù)據(jù)庫第3章Neo4j圖數(shù)據(jù)庫這個章節(jié)將講述Neo4j模型和行為的更多細節(jié)。3.1.節(jié)點構成一張圖的基本元素是節(jié)點和關系。在Neo4j中,節(jié)點和關系都可以包含\o"3.3.
屬性"屬性。節(jié)點經(jīng)常被用于表示一些_實體_,但依賴關系也一樣可以表示實體。下面讓我們認識一個最簡單的節(jié)點,他只有一個屬性,屬性名是name,屬性值是Marko:3.2.關系節(jié)點之間的關系是圖數(shù)據(jù)庫很重要的一部分。通過關系可以找到很多關聯(lián)的數(shù)據(jù),比如節(jié)點集合,關系集合以及他們的\o"3.3.
屬性"屬性集合。一個關系連接兩個節(jié)點,必須有一個開始節(jié)點和結束節(jié)點。因為關系總是直接相連的,所以對于一個節(jié)點來說,與他關聯(lián)的關系看起來有輸入/輸出兩個方向,這個特性對于我們遍歷圖非常有幫助:關系在任一方向都會被遍歷訪問。這意味著我們并不需要在不同方向都新增關系。而關系總是會有一個方向,所以當這個方向對你的應用沒有意義時你可以忽略方向。特別注意一個節(jié)點可以有一個關系是指向自己的:為了將來增強遍歷圖中所有的關系,我們需要為關系設置類型。注意關鍵字type在這可能會被誤解,你其實可以把他簡單的理解為一個標簽而已。下面的例子是一個有兩種關系的最簡單的社會化網(wǎng)絡圖。表3.1.使用到的關系和關系類型功能實現(xiàn)getwhoapersonfollowsoutgoingfollowsrelationships,depthonegetthefollowersofapersonincomingfollowsrelationships,depthonegetwhoapersonblocksoutgoingblocksrelationships,depthonegetwhoapersonisblockedbyincomingblocksrelationships,depthone下面的放里是一個簡單的文件系統(tǒng),包括一些符號軟鏈接:根據(jù)你看到的,你在遍歷的時候會用到關系的方向和關系的類型。WhatHowgetthefullpathofafileincomingfilerelationshipsgetallpathsforafileincomingfileandsymboliclinkrelationshipsgetallfilesinadirectoryoutgoingfileandsymboliclinkrelationships,depthonegetallfilesinadirectory,excludingsymboliclinksoutgoingfilerelationships,depthonegetallfilesinadirectory,recursivelyoutgoingfileandsymboliclinkrelationships3.3.屬性節(jié)點和關系都可以設置自己的屬性。屬性是由Key-Value鍵值對組成,鍵名是字符串。屬性值是要么是原始值,要么是原始值類型的一個數(shù)組。比如+String+,+int+和i+int[]+都是合法的。注意null不是一個合法的屬性值。Nulls能代替模仿一個不存在的Key。表3.2.屬性值類型TypeDescriptionValuerangebooleantrue/falsebyte8-bitinteger-128to127,inclusiveshort16-bitinteger-32768to32767,inclusiveint32-bitinteger-2147483648to2147483647,inclusivelong64-bitinteger-9223372036854775808to9223372036854775807,inclusivefloat32-bitIEEE754floating-pointnumberdouble64-bitIEEE754floating-pointnumberchar16-bitunsignedintegersrepresentingUnicodecharactersu0000touffff(0to65535)StringsequenceofUnicodecharacters如果要了解float/double類型的更多細節(jié),請參考:JavaLanguageSpecification。3.4.路徑路徑由至少一個節(jié)點,通過各種關系連接組成,經(jīng)常是作為一個查詢或者遍歷的結果。最短的路徑是0長度的像下面這樣:長度為1的路徑如下:3.5.遍歷(Traversal)遍歷一張圖就是按照一定的規(guī)則,跟隨他們的關系,訪問關聯(lián)的的節(jié)點集合。最多的情況是只有一部分子圖被訪問到,因為你知道你對那一部分節(jié)點或者關系感興趣。Neo4j提供了遍歷的API,可以讓你指定遍歷規(guī)則。最簡單的設置就是設置遍歷是寬度優(yōu)先還是深度優(yōu)先。想對遍歷框架有一個深入的了解,請參考章節(jié):tutorial-traversal。想了解更多的Java代碼范例,請參考章節(jié):tutorials-java-embedded-traversal。其他查詢圖的方式還有cypher-query-lang,Cypher和gremlin-plugin,Gremlin。部分II.教程教程這部分將指導我們如何建立你的環(huán)境并使用Neo4j進行開發(fā)。它將從最簡單的HelloWorld到圖數(shù)據(jù)庫的高級應用逐一介紹。第4章在Java應用中使用Neo4j在Java中采用嵌入方式使用Neo4j是非常方便的。在這個章節(jié)中,你將找到所有你想了解的—從基本環(huán)境的搭建到用你的數(shù)據(jù)做一些實際有用的事情。在Java應用中使用Neo4j是非常容易的。正這個章節(jié)中你將找到你需要的一切?—?從開發(fā)環(huán)境的建立到用你的數(shù)據(jù)做一些有用的事情。4.1.將Neo4j引入到你的項目工程中在選擇了適合你的平臺的editions,edition后,只需要引入Neo4j的jars文件到你的工程的構造路徑中,你就可以在你的工程中使用Neo4j數(shù)據(jù)庫了。下面的章節(jié)將展示如何完成引入,要么通過直接改變構造路徑,要么使用包依賴管理。4.1.1.增加Neo4j的庫文件到構造路徑中可以通過下面任意一種方式得到需要的jar文件:解壓Neo4j下載的壓縮包,我們需要使用的jars文件都包括在lib目錄中。直接使用Maven中心倉庫的jars文件。將jars引入到你的項目工程中:JDKtools增加到-classpath中Eclipse右鍵點擊工程然后選擇BuildPath→ConfigureBuildPath。在對話框中選擇AddExternalJARs,瀏覽到Neo4j的'lib/'目錄并選擇所有的jar文件。另外一種方式是使用UserLibraries。IntelliJIDEA看Libraries,GlobalLibraries,andtheConfigureLibrarydialog了解詳情。NetBeans在工程的Libraries點擊鼠標右鍵,選擇AddJAR/Folder,瀏覽到Neo4j的'lib/'目錄選擇里面的所有jar文件。你也可以從工程節(jié)點來管理庫文件。詳細情況請查看管理一個工程的classpath。4.1.2.將Neo4j作為一個依賴添加想總覽一下主要的Neo4j構件,請查看editions。列在里面的構件都是包含實際Neo4j實現(xiàn)的頂級構件。你既可以使用頂級構件也可以直接引入單個的組件。在這的范例使用的是頂級構件的方式。MavenMavendependency.123456789101112<project>...<dependencies><dependency><groupId>org.neo4j</groupId><artifactId>neo4j</artifactId><version>1.8</version></dependency>...</dependencies>...</project>參數(shù)artifactId可以在editions找到。EclipseandMaven在Eclipse中開發(fā),推薦安裝插件m2eplugin讓Maven管理classpath來代替上面的方案。這樣的話,你既可以通過Maven命令行來編譯你的工程,也可以通過Maven命令自動生成一個Eclipse工作環(huán)境以便進行開發(fā)。Ivy確保能解決來自MavenCentral的依賴問題,比如我們在你的'ivysettings.xml'文件中使用下面的配置選項:1234567891011<ivysettings><settingsdefaultResolver="main"/><resolvers><chainname="main"><filesystemname="local"><artifactpattern="${ivy.settings.dir}/repository/[artifact]-[revision].[ext]"/></filesystem><ibiblioname="maven_central"root="/maven2/"m2compatible="true"/></chain></resolvers></ivysettings>有了這個,你就可以通過增加下面這些內容到你的'ivy.xml'中來引入Neo4j:1234567..<dependencies>..<dependencyorg="org.neo4j"name="neo4j"rev="1.8"/>..</dependencies>..參數(shù)name可以在editions找到。Gradle下面的范例演示了用Gradle生成一個腳本來引入Neo4j庫文件。12345678defneo4jVersion="1.8"applyplugin:'java'repositories{mavenCentral()}dependencies{compile"org.neo4j:neo4j:${neo4jVersion}"}參數(shù)coordinates(在范例中的org.neo4j:neo4j)可以在editions找到。4.1.3.啟動和停止為了創(chuàng)建一個新的數(shù)據(jù)庫或者打開一個已經(jīng)存在的,你需要實例化一個+EmbeddedGraphDatabase+對象。12graphDb=newGraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);registerShutdownHook(graphDb);注意EmbeddedGraphDatabase實例可以在多個線程中共享。然而你不能創(chuàng)建多個實例來指向同一個數(shù)據(jù)庫。為了停止數(shù)據(jù)庫,你需要調用方法shutdown():1graphDb.shutdown();為了確保Neo4j被正確關閉,你可以為它增加一個關閉鉤子方法:1234567891011121314privatestaticvoidregisterShutdownHook(finalGraphDatabaseServicegraphDb){//RegistersashutdownhookfortheNeo4jinstancesothatit//shutsdownnicelywhentheVMexits(evenifyou"Ctrl-C"the//runningexamplebeforeit'scompleted)Runtime.getRuntime().addShutdownHook(newThread(){@Overridepublicvoidrun(){graphDb.shutdown();}});}如果你只想通過只讀方式瀏覽數(shù)據(jù)庫,請使用EmbeddedReadOnlyGraphDatabase。想通過配置設置來啟動Neo4j,一個Neo4j屬性文件可以像下面這樣加載:1234GraphDatabaseServicegraphDb=newGraphDatabaseFactory().newEmbeddedDatabaseBuilder("target/database/location").loadPropertiesFromFile(pathToConfig+"perties").newGraphDatabase();或者你可以編程創(chuàng)建你自己的Map<String,String>來代替。想了解更多配置設置的細節(jié),請參考:embedded-configuration。4.2.你好,世界正這里可以學習如何創(chuàng)建和訪問節(jié)點和關系。關于建立工程環(huán)境的信息,請參考:\o"4.1.
將Neo4j引入到你的項目工程中"第4.1節(jié)“將Neo4j引入到你的項目工程中”。從\o"2.1.
什么是圖數(shù)據(jù)庫?"第2.1節(jié)“什么是圖數(shù)據(jù)庫?”中,我們還記得,一個Neo4j圖數(shù)據(jù)庫由以下幾部分組成:相互關聯(lián)的節(jié)點有一定的關系存在在節(jié)點和關系上面有一些屬性。所有的關系都有一個類型。比如,如果一個圖數(shù)據(jù)庫實例表示一個社網(wǎng)絡,那么一個關系類型可能叫KNOWS。如果一個類型叫KNOWS的關系連接了兩個節(jié)點,那么這可能表示這兩個人呼吸認識。一個圖數(shù)據(jù)庫中大量的語義都被編碼成關系的類型來使用。雖然關系是直接相連的,但他們也可以不用考慮他們遍歷的方向而互相遍歷對方。提示范例源代碼下載地址:EmbeddedNeo4j.java4.2.1.準備圖數(shù)據(jù)庫關系類型可以通過enum創(chuàng)建。正這個范例中我們之需要一個單獨的關系類型。下面是我們的定義:1234privatestaticenumRelTypesimplementsRelationshipType{KNOWS}我們頁準備一些需要用到的參數(shù):1234GraphDatabaseServicegraphDb;NodefirstNode;NodesecondNode;Relationshiprelationship;下一步將啟動數(shù)據(jù)庫服務器了。逐一如果給定的保持數(shù)據(jù)庫的目錄如果不存在,那么它會自動創(chuàng)建。12graphDb=newGraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);registerShutdownHook(graphDb);注意:啟動一個圖數(shù)據(jù)庫是一個非常重(耗費資源)的操作,所以不要每次你需要與數(shù)據(jù)庫進行交互操作時都去啟動一個新的實例。這個實例可以被多個線程共享。事務是線程安全的。就像你上面所看到的一樣,我們注冊了一個關閉數(shù)據(jù)庫的鉤子用來確保在JVM退出時數(shù)據(jù)庫已經(jīng)被關閉?,F(xiàn)在是時候與數(shù)據(jù)庫進行交互了。4.2.2.在一個事務中完成多次寫數(shù)據(jù)庫操作所有的寫操作(創(chuàng)建,刪除以及更新)都是在一個事務中完成的。這是一個有意的設計,因為我們相信事務是使用一個企業(yè)級數(shù)據(jù)庫中非常重要的一部分?,F(xiàn)在,在Neo4j中的事務處理是非常容易的:12345678910Transactiontx=graphDb.beginTx();try{//Updatingoperationsgoheretx.success();}finally{tx.finish();}要了解更多關于事務的細節(jié),請參考:transactions和JavaAPI中的事務接口。4.2.3.創(chuàng)建一個小型圖數(shù)據(jù)庫現(xiàn)在,讓我們來創(chuàng)建一些節(jié)點。API是非常直觀的。你也隨意查看在/neo4j/1.8/apidocs/的JavaDocs文檔。它們也被包括正發(fā)行版中。這兒展示了如何創(chuàng)建一個小型圖數(shù)據(jù)庫,數(shù)據(jù)庫中包括兩個節(jié)點并用一個關系相連,節(jié)點和關系還包括一些屬性:1234567firstNode=graphDb.createNode();firstNode.setProperty("message","Hello,");secondNode=graphDb.createNode();secondNode.setProperty("message","World!");relationship=firstNode.createRelationshipTo(secondNode,RelTypes.KNOWS);relationship.setProperty("message","braveNeo4j");現(xiàn)在我們有一個圖數(shù)據(jù)庫看起來像下面這樣:圖4.1.HelloWorld圖數(shù)據(jù)庫4.2.4.打印結果在我們創(chuàng)建我們的圖數(shù)據(jù)庫后,讓我們從中讀取數(shù)據(jù)并打印結果。123System.out.print(firstNode.getProperty("message"));System.out.print(relationship.getProperty("message"));System.out.print(secondNode.getProperty("message"));輸出結果:Hello,braveNeo4jWorld!4.2.5.移除數(shù)據(jù)在這種情況下我們將在提交之前移除數(shù)據(jù):1234//let'sremovethedatafirstNode.getSingleRelationship(RelTypes.KNOWS,Direction.OUTGOING).delete();firstNode.delete();secondNode.delete();注意刪除一個仍然有關系的節(jié)點,當事務提交是會失敗。這是為了確保關系始終有一個開始節(jié)點和結束節(jié)點。4.2.6.關閉圖數(shù)據(jù)庫最后,當應用完成后關閉數(shù)據(jù)庫:1graphDb.shutdown();4.3.帶索引的用戶數(shù)據(jù)庫你有一個用戶數(shù)據(jù)庫,希望通過名稱查找到用戶。首先,下面這是我們想創(chuàng)建的數(shù)據(jù)庫結構:圖4.2.用戶節(jié)點空間預覽其中,參考節(jié)點連接了一個用戶參考節(jié)點,而真實的所有用戶都連接在用戶參考節(jié)點上面。提示范例中的源代碼下載地址:EmbeddedNeo4jWithIndexing.java首先,我們定義要用到的關系類型:12345privatestaticenumRelTypesimplementsRelationshipType{USERS_REFERENCE,USER}然后,我們創(chuàng)建了兩個輔助方法來處理用戶名稱以及往數(shù)據(jù)庫新增用戶:123456789101112privatestaticStringidToUserName(finalintid){return"user"+id+"@";}privatestaticNodecreateAndIndexUser(finalStringusername){Nodenode=graphDb.createNode();node.setProperty(USERNAME_KEY,username);nodeIndex.add(node,USERNAME_KEY,username);returnnode;}下一步我們將啟動數(shù)據(jù)庫:123graphDb=newGraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);nodeIndex=graphDb.index().forNodes("nodes");registerShutdownHook();是時候新增用戶了:1234567891011121314Transactiontx=graphDb.beginTx();try{//CreateuserssubreferencenodeNodeusersReferenceNode=graphDb.createNode();graphDb.getReferenceNode().createRelationshipTo(usersReferenceNode,RelTypes.USERS_REFERENCE);//CreatesomeusersandindextheirnameswiththeIndexServicefor(intid=0;id<100;id++){NodeuserNode=createAndIndexUser(idToUserName(id));usersReferenceNode.createRelationshipTo(userNode,RelTypes.USER);}通過Id查找用戶:12345intidToFind=45;NodefoundUser=nodeIndex.get(USERNAME_KEY,idToUserName(idToFind)).getSingle();System.out.println("Theusernameofuser"+idToFind+"is"+foundUser.getProperty(USERNAME_KEY));4.4.基本的單元測試Neo4j的單元測試的基本模式通過下面的范例來闡釋。要訪問Neo4j測試功能,你應該把neo4j-kernel'tests.jar'新增到你的類路徑中。你可以從MavenCentral:org.neo4j:neo4j-kernel下載到需要的jars。使用Maven作為一個依賴管理,你通常會正pom.xml中增加依賴配置:Maven依賴.1234567891011121314<project>...<dependencies><dependency><groupId>org.neo4j</groupId><artifactId>neo4j-kernel</artifactId><version>${neo4j-version}</version><type>test-jar</type><scope>test</scope></dependency>...</dependencies>...</project>_${neo4j-version}是Neo4j的版本號。_到此,我們已經(jīng)準備好進行單元測試編碼了。提示范例源代碼下載地址:Neo4jBasicTest.java每一次開始單元測試之前,請創(chuàng)建一個干凈的數(shù)據(jù)庫:12345@BeforepublicvoidprepareTestDatabase(){graphDb=newTestGraphDatabaseFactory().newImpermanentDatabaseBuilder().newGraphDatabase();}在測試完成之后,請關閉數(shù)據(jù)庫:12345@AfterpublicvoiddestroyTestDatabase(){graphDb.shutdown();}在測試期間,創(chuàng)建節(jié)點并檢查它們是否存在,并在一個事務中結束寫操作。123456789101112131415161718192021222324252627Transactiontx=graphDb.beginTx();Noden=null;try{n=graphDb.createNode();n.setProperty("name","Nancy");tx.success();}catch(Exceptione){tx.failure();}finally{tx.finish();}//Thenodeshouldhaveanidgreaterthan0,whichistheidofthe//referencenode.assertThat(n.getId(),is(greaterThan(0l)));//Retrieveanodebyusingtheidofthecreatednode.Theid'sand//propertyshouldmatch.NodefoundNode=graphDb.getNodeById(n.getId());assertThat(foundNode.getId(),is(n.getId()));assertThat((String)foundNode.getProperty("name"),is("Nancy"));如果你想查看創(chuàng)建數(shù)據(jù)庫的參數(shù)配置,你可以這樣:12345Map<String,String>config=newHashMap<String,String>();config.put("neostore.nodestore.db.mapped_memory","10M");config.put("string_block_size","60");config.put("array_block_size","300");GraphDatabaseServicedb=newImpermanentGraphDatabase(config);4.5.遍歷查詢了解更多關于遍歷查詢的信息,請參考:tutorial-traversal。了解更多關于遍歷查詢范例的信息,請參考:\o"第
7
章
數(shù)據(jù)模型范例"第7章數(shù)據(jù)模型范例。4.5.1.黑客帝國對于上面的黑客帝國范例的遍歷查詢,這次使用新的遍歷API:提示范例源代碼下載地址:NewMatrix.java朋友以及朋友的朋友.123456789privatestaticTraversergetFriends(finalNodeperson){TraversalDescriptiontd=Traversal.description().breadthFirst().relationships(RelTypes.KNOWS,Direction.OUTGOING).evaluator(Evaluators.excludeStartPosition());returntd.traverse(person);}讓我們只想一次真實的遍歷查詢并打印結果:1234567891011intnumberOfFriends=0;Stringoutput=neoNode.getProperty("name")+"'sfriends:\n";TraverserfriendsTraverser=getFriends(neoNode);for(PathfriendPath:friendsTraverser){output+="Atdepth"+friendPath.length()+"=>"+friendPath.endNode().getProperty("name")+"\n";numberOfFriends++;}output+="Numberoffriendsfound:"+numberOfFriends+"\n";輸出結果:123456ThomasAnderson'sfriends:Atdepth1=>TrinityAtdepth1=>MorpheusAtdepth2=>CypherAtdepth3=>AgentSmith找到朋友的數(shù)量:4誰編寫了黑客帝國?.12345678910privatestaticTraverserfindHackers(finalNodestartNode){TraversalDescriptiontd=Traversal.description().breadthFirst().relationships(RelTypes.CODED_BY,Direction.OUTGOING).relationships(RelTypes.KNOWS,Direction.OUTGOING).evaluator(Evaluators.includeWhereLastRelationshipTypeIs(RelTypes.CODED_BY));returntd.traverse(startNode);}打印輸出結果:1234567891011Stringoutput="Hackers:\n";intnumberOfHackers=0;Traversertraverser=findHackers(getNeoNode());for(PathhackerPath:traverser){output+="Atdepth"+hackerPath.length()+"=>"+hackerPath.endNode().getProperty("name")+"\n";numberOfHackers++;}output+="Numberofhackersfound:"+numberOfHackers+"\n";現(xiàn)在我們知道是誰編寫了黑客帝國:123Hackers:Atdepth4=>TheArchitect找到hackers的數(shù)量:1游走一個有序路徑這個范例展示了如何通過一個路徑上下文控制一條路徑的表現(xiàn)。提示范例源代碼下載地址:OrderedPath.java創(chuàng)建一個圖數(shù)據(jù)庫.12345678NodeA=db.createNode();NodeB=db.createNode();NodeC=db.createNode();NodeD=db.createNode();A.createRelationshipTo(B,REL1);B.createRelationshipTo(C,REL2);C.createRelationshipTo(D,REL3);A.createRelationshipTo(C,REL2);現(xiàn)在,關系(REL1→REL2→REL3)的順序保存在一個ArrayList對象中。當遍歷的時候,Evaluator能針對它進行檢查,確保只有擁有預定義關系順序的路徑才會被包括并返回:定義如何游走這個路徑.123456789101112131415161718192021222324finalArrayList<RelationshipType>orderedPathContext=newArrayList<RelationshipType>();orderedPathContext.add(REL1);orderedPathContext.add(withName("REL2"));orderedPathContext.add(withName("REL3"));TraversalDescriptiontd=Traversal.description().evaluator(newEvaluator(){@OverridepublicEvaluationevaluate(finalPathpath){if(path.length()==0){returnEvaluation.EXCLUDE_AND_CONTINUE;}RelationshipTypeexpectedType=orderedPathContext.get(path.length()-1);booleanisExpectedType=path.lastRelationship().isType(expectedType);booleanincluded=path.length()==orderedPathContext.size()&&isExpectedType;booleancontinued=path.length()<orderedPathContext.size()&&isExpectedType;returnEvaluation.of(included,continued);}});執(zhí)行一次遍歷查詢并返回結果.123456Traversertraverser=td.traverse(A);PathPrinterpathPrinter=newPathPrinter("name");for(Pathpath:traverser){output+=Traversal.pathToString(path,pathPrinter);}輸出結果:1(A)--[REL1]-->(B)--[REL2]-->(C)--[REL3]-->(D)在這種情況下我們使用一個自定義類來格式化路徑輸出。下面是它的具體實現(xiàn):12345678910111213141516171819202122232425262728293031staticclassPathPrinterimplementsTraversal.PathDescriptor<Path>{privatefinalStringnodePropertyKey;publicPathPrinter(StringnodePropertyKey){this.nodePropertyKey=nodePropertyKey;}@OverridepublicStringnodeRepresentation(Pathpath,Nodenode){return"("+node.getProperty(nodePropertyKey,"")+")";}@OverridepublicStringrelationshipRepresentation(Pathpath,Nodefrom,Relationshiprelationship){Stringprefix="--",suffix="--";if(from.equals(relationship.getEndNode())){prefix="<--";}else{suffix="-->";}returnprefix+"["+relationship.getType().name()+"]"+suffix;}}為了了解更多關于Path的有選擇的輸出的細節(jié),請參考:Traversal類。注意下面的范例使用了一個已經(jīng)廢棄的遍歷API。它與新的遍歷查詢API共享底層實現(xiàn),所以它們的性能是一樣的。比較起來它提供的功能非常有限。4.5.2.老的遍歷查詢API這是我們想遍歷查詢的第一個圖數(shù)據(jù)庫:圖4.3.黑客帝國節(jié)點空間預覽提示范例源代碼下載地址:Matrix.java朋友以及朋友的朋友.1234567privatestaticTraversergetFriends(finalNodeperson){returnperson.traverse(Order.BREADTH_FIRST,StopEvaluator.END_OF_GRAPH,ReturnableEvaluator.ALL_BUT_START_NODE,RelTypes.KNOWS,Direction.OUTGOING);}讓我們執(zhí)行一次真實的遍歷查詢并打印結果:123456789101112intnumberOfFriends=0;Stringoutput=neoNode.getProperty("name")+"'sfriends:\n";TraverserfriendsTraverser=getFriends(neoNode);for(NodefriendNode:friendsTraverser){output+="Atdepth"+friendsTraverser.currentPosition().depth()+"=>"+friendNode.getProperty("name")+"\n";numberOfFriends++;}output+="Numberoffriendsfound:"+numberOfFriends+"\n";下面是輸出結果:123456ThomasAnderson的朋友們:Atdepth1=>TrinityAtdepth1=>MorpheusAtdepth2=>CypherAtdepth3=>AgentSmith一共找到朋友數(shù)量:4是誰編寫了黑客帝國呢?12345678910111213141516privatestaticTraverserfindHackers(finalNodestartNode){returnstartNode.traverse(Order.BREADTH_FIRST,StopEvaluator.END_OF_GRAPH,newReturnableEvaluator(){@OverridepublicbooleanisReturnableNode(finalTraversalPositioncurrentPos){return!currentPos.isStartNode()&¤tPos.lastRelationshipTraversed().isType(RelTypes.CODED_BY);}},RelTypes.CODED_BY,Direction.OUTGOING,RelTypes.KNOWS,Direction.OUTGOING);}輸出結果:123456789101112Stringoutput="Hackers:\n";intnumberOfHackers=0;Traversertraverser=findHackers(getNeoNode());for(NodehackerNode:traverser){output+="Atdepth"+traverser.currentPosition().depth()+"=>"+hackerNode.getProperty("name")+"\n";numberOfHackers++;}output+="Numberofhackersfound:"+numberOfHackers+"\n";現(xiàn)在我們知道是誰編寫了黑客帝國:123Hackers:Atdepth4=>TheArchitect找到hackers的數(shù)量:14.5.3.在遍歷查詢中的唯一路徑這個范例演示了節(jié)點唯一性的使用。下面是一個想象的有多個負責人的領域圖,這些負責人有它們增加的寵物,而這些寵物又生產(chǎn)了它的后代。圖4.4.后代范例圖為了返回Pet0的所有后代,要求與Pet0必須有owns和Principal1關系(實際上只有Pet1和Pet3),遍歷查詢的Uniqueness應該設置成NODE_PATH來代替默認的NODE_GLOBAL以至于節(jié)點可以被遍歷不止一次,而且那些有不同節(jié)點但能有一些相同的路徑(比如開始節(jié)點和結束節(jié)點)也能被返回。1234567891011121314151617finalNodetarget=data.get().get("Principal1");TraversalDescriptiontd=Traversal.description().uniqueness(Uniqueness.NODE_PATH).evaluator(newEvaluator(){@OverridepublicEvaluationevaluate(Pathpath){if(path.endNode().equals(target)){returnEvaluation.INCLUDE_AND_PRUNE;}returnEvaluation.EXCLUDE_AND_CONTINUE;}});Traverserresults=td.traverse(start);這將返回下面的路徑:12(3)--[descendant,0]-->(1)<--[owns,3]--(5)(3)--[descendant,2]-->(4)<--[owns,5]--(5)在path.toString()的默認實現(xiàn)中,(1)--[knows,2]-->(4)表示一個ID=1的節(jié)點通過一個ID=2,關系類型為knows的關系連接到了一個ID=4的節(jié)點上。讓我們從一個舊的中創(chuàng)建一個新的TraversalDescription,并且設置uniqueness為NODE_GLOBAL來查看它們之間的區(qū)別。提示TraversalDescription對象是不變的,因此我們必須使用一個新的實例來返回新的uniqueness設置。12TraversalDescriptionnodeGlobalTd=td.uniqueness(Uniqueness.NODE_GLOBAL);results=nodeGlobalTd.traverse(start);現(xiàn)在只有一條路徑返回:1(3)--[descendant,0]-->(1)<--[owns,3]--(5)4.5.4.社交網(wǎng)絡注意:下面的范例使用了處于實驗階段的遍歷查詢API。社交網(wǎng)絡(在互聯(lián)網(wǎng)上也被稱為社交圖)是天然的用圖來表示的模型。下面的范例演示了一個非常簡單的社交模型,它連接了朋友并關注了好友動態(tài)。提示范例源代碼下載地址:socnet簡單的社交模型圖4.5.社交網(wǎng)絡數(shù)據(jù)模型一個社交網(wǎng)絡的數(shù)據(jù)模型是簡漂亮的:有名稱的Persons和有時間戳文本的StatusUpdates。這些實體然后通過特殊的關系連接在一起。Personfriend:連接兩個不同Person實例的關系(不能連接自己)status:連接到最近的StatusUpdateStatusUpdatenext:指向在主線上的下一個StatusUpdate,是在當前這個狀態(tài)更新之前發(fā)生的狀態(tài)圖實例一個Person的StatusUpdate列表是一個鏈表。表頭(最近動態(tài))可以通過下一個status找到。每一個隨后的StatusUpdate都通過關系next相連。這是一個AndreasKollegger微博記錄圖早上走路上班的范例:為了讀取狀態(tài)更新情況,我們可以創(chuàng)建一個遍歷查詢,比如:123TraversalDescriptiontraversal=Traversal.description().depthFirst().relationships(NEXT);這給了我們一個遍歷查詢,它將從一個StatusUpdate開始,并一直跟隨狀態(tài)的主線直到它們運行結束。遍歷查詢是懶加載模式所以當我們處理成千上萬狀態(tài)的時候性能一樣很好?—?除非我們真實使用它們,否在它們不會被加載。活動流一旦我們有了朋友,而且它們有了狀態(tài)消息,我們可能想讀取我們的朋友的消息動態(tài),按時間倒序排列?—?最新的動態(tài)在前面。為了實現(xiàn)這個,我們可以通過下面幾個步驟:抓取所有的好友動態(tài)放入一個列表?—?最新的排前面。對列表進行排序。返回列表中的第一個記錄。如果第一個迭代器為空,則把它從列表移除。否則,在這個迭代器中獲取下一個記錄。跳轉到步驟2直到在列表中沒有任何記錄。這個隊列看起來像這樣。代碼實現(xiàn)像這樣:1234567891011121314PositionedIterator<StatusUpdate>first=statuses.get(0);StatusUpdatereturnVal=first.current();if(!first.hasNext()){statuses.remove(0);}else{first.next();sort();}returnreturnVal;4.6.領域實體這個地方演示了當使用Neo4j時控制領域實體的一個方法。使用的原則是將實體封裝到節(jié)點上(這個方法也可以用在關系上)。提示范例源代碼下載地址:Person.java馬上,保存節(jié)點并且讓它在包里可以被訪問:1234567891011privatefinalNodeunderlyingNode;Person(NodepersonNode){this.underlyingNode=personNode;}protectedNodegetUnderlyingNode(){returnunderlyingNode;}分配屬性給節(jié)點:1234publicStringgetName(){return(String)underlyingNode.getProperty(NAME);}確保重載這些方法:123456789101112131415161718@OverridepublicinthashCode(){returnunderlyingNode.hashCode();}@Overridepublicbooleanequals(Objecto){returnoinstanceofPerson&&underlyingNode.equals(((Person)o).getUnderlyingNode());}@OverridepublicStringtoString(){return"Person["+getName()+"]";}4.7.圖算法范例提示范例源代碼下載地址:PathFindingExamplesTest.java計算正連個節(jié)點之間的最短路徑(最少數(shù)目的關系):12345678910111213141516NodestartNode=graphDb.createNode();NodemiddleNode1=graphDb.createNode();NodemiddleNode2=graphDb.createNode();NodemiddleNode3=graphDb.createNode();NodeendNode=graphDb.createNode();createRelationshipsBetween(startNode,middleNode1,endNode);createRelationshipsBetween(startNode,middleNode2,middleNode3,endNode);//WillfindtheshortestpathbetweenstartNodeandendNodevia//"MY_TYPE"relationships(inOUTGOINGdirection),likef.ex:////(startNode)-->(middleNode1)-->(endNode)//PathFinder<Path>finder=GraphAlgoFactory.shortestPath(Traversal.expanderForTypes(ExampleTypes.MY_TYPE,Direction.OUTGOING),15);Iterable<Path>paths=finder.findAllPaths(startNode,endNode);使用迪科斯徹(Dijkstra)算法解決有向圖中任意兩個頂點之間的最短路徑問題。1234567PathFinder<WeightedPath>finder=GraphAlgoFactory.dijkstra(Traversal.expanderForTypes(ExampleTypes.MY_TYPE,Direction.BOTH),"cost");WeightedPathpath=finder.findSinglePath(nodeA,nodeB);//Gettheweightforthefoundpathpath.weight();使用A*算法是解決靜態(tài)路網(wǎng)中求解最短路最有效的方法。這兒是我們的范例圖:123456789101112131415161718192021NodenodeA=createNode("name","A","x",0d,"y",0d);NodenodeB=createNode("name","B","x",7d,"y",0d);NodenodeC=createNode("name","C","x",2d,"y",1d);RelationshiprelAB=createRelationship(nodeA,nodeC,"length",2d);RelationshiprelBC=createRelationship(nodeC,nodeB,"length",3d);RelationshiprelAC=createRelationship(nodeA,nodeB,"length",10d);EstimateEvaluator<Double>estimateEvaluator=newEstimateEvaluator<Double>(){publicDoublegetCost(finalNodenode,finalNodegoal){doubledx=(Double)node.getProperty("x")-(Double)goal.getProperty("x");doubledy=(Double)node.getProperty("y")-(Double)goal.getProperty("y");doubleresult=Math.sqrt(Math.pow(dx,2)+Math.pow(dy,2));returnresult;}};PathFinder<WeightedPath>astar=GraphAlgoFactory.aStar(Traversal.expanderForAllTypes(),CommonEvaluators.doubleCostEvaluator("length"),estimateEvaluator);WeightedPathpath=astar.findSinglePath(nodeA,nodeB);4.8.讀取一個管理配置屬性EmbeddedGraphDatabase類包括了一個/neo4j/1.8/apidocs/org/neo4j/kernel/EmbeddedGraphDatabase.html#getManagementBean%28java.lang.Class%29[方便的方法]來獲取Neo4j管理用的beans。一般JMX服務也能使用,但比起你自己編碼不如使用這概述的方法。提示范例源代碼下載地址:JmxTest.java這個范例演示了如何得到一個圖數(shù)據(jù)庫的開始時間:12345678privatestaticDategetStartTimeFromManagementBean(GraphDatabaseServicegraphDbService){GraphDatabaseAPIgraphDb=(GraphDatabaseAPI)graphDbService;Kernelkernel=graphDb.getSingleManagementBean(Kernel.class);DatestartTime=kernel.getKernelStartTime();returnstartTime;}不同的Neo4j版本,你將使用不同的管理beans設置。了解所有Neo4j版本的信息,請參考:org.neo4j.jmx。了解Neo4j高級版和企業(yè)版的信息,請參考:org.neo4j.management。4.9.OSGi配置4.9.1.SimpleOSGiActivator腳本在OSGi關聯(lián)的上下文比如大量的應用服務器(e.g.Glassfish)和基于Eclipse的系統(tǒng)中,Neo4j能被明確地建立起來而不是通過Java服務加載機制來發(fā)現(xiàn)。4.9.1.SimpleOSGiActivator腳本如同在下面的范例中看到的一樣,為了代替依賴Neo4j內核的類加載,Neo4jBundle被作為庫bundles,而像IndexProviders和CacheProviders這樣的服務被明確地實例化,配置和注冊了秩序。只需要確保必要的jars,所以所有必須的類都被導出并且包括這Activator。1234567891011121314151617181920212223242526272829303132333435363738394041424publicclassNeo4jActivatorimplementsBundleActivator{privatestaticGraphDatabaseServicedb;privateServiceRegistrationserviceRegistration;privateServiceR
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 浙江警官職業(yè)學院《醫(yī)學信息檢索與利用(4)》2023-2024學年第二學期期末試卷
- 甘肅林業(yè)職業(yè)技術學院《鐵路旅客運輸》2023-2024學年第二學期期末試卷
- 乘法-隊列表演(二)教學設計-2023-2024學年三年級下冊數(shù)學北師大版
- 一個時代歌者的赤子深情-名著導讀:《艾青詩選》如何讀詩(教學設計)九年級語文上冊同步高效課堂(統(tǒng)編版)
- 咸陽師范學院《專業(yè)新聞與深度報道》2023-2024學年第二學期期末試卷
- 遼寧何氏醫(yī)學院《建筑室內聲學設計》2023-2024學年第二學期期末試卷
- 成都信息工程大學《高聚物合成工藝及設備》2023-2024學年第二學期期末試卷
- 泉州輕工職業(yè)學院《文化學導論》2023-2024學年第二學期期末試卷
- Unit 2 Were Family!Section B 2a-2b 教學設計2024-2025學年人教版(2024)七年級英語上冊
- 中山大學《黑白圖像》2023-2024學年第二學期期末試卷
- 北京市東城區(qū)2025年公開招考539名社區(qū)工作者高頻重點提升(共500題)附帶答案詳解
- 2025福建福州地鐵集團限公司運營分公司校園招聘高頻重點提升(共500題)附帶答案詳解
- 2025至2030年中國電子護眼臺燈數(shù)據(jù)監(jiān)測研究報告
- 2025年浙江省溫州樂清市融媒體中心招聘4人歷年高頻重點提升(共500題)附帶答案詳解
- 2025夏季廣東廣州期貨交易所招聘高頻重點提升(共500題)附帶答案詳解
- 2025上海市嘉定工業(yè)區(qū)農村青年干部招聘22人歷年高頻重點提升(共500題)附帶答案詳解
- 《獸醫(yī)基礎》練習題及參考答案
- 2025年煤礦探放水證考試題庫
- 農業(yè)機械設備運輸及調試方案
- 污水處理設備的故障處理指南考核試卷
- ps 課件教學課件
評論
0/150
提交評論