浙江注冊公司網(wǎng)站seo互聯(lián)網(wǎng)營銷培訓
Neo4j的簡介
Neo4j是用Java實現(xiàn)的開源NoSQL圖數(shù)據(jù)庫。從2003年開始開發(fā),2007年正式發(fā)布第一版,其源碼托管于GitHtb。Neo4j作為圖數(shù)據(jù)庫中的代表產(chǎn)品,已經(jīng)在眾多的行業(yè)項目中進行了應用,如:網(wǎng)絡管理、軟件分析、組織和項目管理、社交項目等方面。
Neo4j的安裝(docker安裝)
通過docker拉起鏡像
docker pull neo4j:4.4.5
創(chuàng)建/data/neo4j文件夾,用于配置文件夾的掛載
kmdir /data/neo4j
啟動docker容器(需要開啟對應的映射端口,這里需要開放的端口就是 7474,7687)
docker run \
-d \
--restart=always \
--name neo4j \
-p 7474:7474 \
-p 7687:7687 \
-v neo4j:/data \
neo4j:4.4.5
neo4j控制面板的地址:?http://localhost:7474/browser/
初始的賬號為:neo4j,密碼為:neo4j。
?如果出現(xiàn)下面情況,說明neo4j設置了只應許本地連接。
?需要進入容器中修改 neo4f.conf文件
進入neo4j容器
docker exec -it 對應的容器Id /bin/bash
進入/conf文件夾中
cd /conf
?在容器中默認是沒有安裝vim的,所以我需要手動安裝
apt-get update
apt-get install -y vim
修改neo4j.conf中的配置
將Bolt connetor的配置進行修改
dbms.connector.bolt.enabled=true
#dbms.connector.bolt.tls_level=DISABLED
dbms.connector.bolt.listen_address=對應Ip:7687
Neo4j的使用
Neo4j的數(shù)據(jù)結(jié)構(gòu)
- 節(jié)點
-
- 存儲實體數(shù)據(jù),在上圖中,演員、電影都是節(jié)點。
- 可以理解為關(guān)系型數(shù)據(jù)庫中的表。
- 關(guān)系
-
- 存儲節(jié)點之間的關(guān)系。
- 關(guān)系只能有一個類型,必須有開始節(jié)點和結(jié)束節(jié)點以及指向。
- 關(guān)系可以自我循環(huán)引用,但是兩頭永遠不能為空。
- 屬性
-
- 節(jié)點和關(guān)系都可以有屬性,它是由鍵值對組成的。
- 節(jié)點的屬性可以理解為關(guān)系型數(shù)據(jù)庫中的字段。
- 關(guān)系中的屬性進一步的明確了關(guān)系。
- 標簽
-
- 標簽是對節(jié)點的分類,這樣使得構(gòu)建Neo4j數(shù)據(jù)模型更加簡單。
- 在上面的電影案例中,Movie、Person就是標簽。
Cypher使用
1.創(chuàng)建數(shù)據(jù)
//查詢所有數(shù)據(jù)
MATCH (n) RETURN n
//強制刪除所有節(jié)點和關(guān)系,慎用!
MATCH (n) DETACH DELETE n
CREATE (n {name: $value}) RETURN n //創(chuàng)建節(jié)點,該節(jié)點具備name屬性,n為該節(jié)點的變量,創(chuàng)建完成后返回該節(jié)點
CREATE (n:$Tag {name: $value}) //創(chuàng)建節(jié)點,指定標簽
CREATE (n)-[r:KNOWS]->(m) //創(chuàng)建n指向m的關(guān)系,并且指定關(guān)系類型為:KNOWS//示例
CREATE (n {name:'迪士尼營業(yè)部'})
CREATE (n:AGENCY {name:'航頭營業(yè)部'})
//創(chuàng)建浦東新區(qū)轉(zhuǎn)運中心、上海轉(zhuǎn)運中心節(jié)點,并且創(chuàng)建關(guān)系為:IN_LINE,創(chuàng)建完成后返回節(jié)點和關(guān)系
//TLT -> Two Level Transport(二級轉(zhuǎn)運中心)
//OLT -> One Level Transport(一級轉(zhuǎn)運中心)
CREATE (n:TLT {name:'浦東新區(qū)轉(zhuǎn)運中心'}) -[r:IN_LINE]-> (m:OLT {name:'上海轉(zhuǎn)運中心'}) RETURN n,r,m
//關(guān)系也是可以反向,并且可以為關(guān)系中指定屬性
CREATE (n:TLT {name:'浦東新區(qū)轉(zhuǎn)運中心'}) <-[r:OUT_LINE]- (m:OLT {name:'上海轉(zhuǎn)運中心'}) RETURN n,r,m
2.查詢數(shù)據(jù)
查詢數(shù)據(jù)的格式為下:
[MATCH WHERE] //條件查詢
[WITH [ORDER BY] [SKIP] [LIMIT]] //查詢的結(jié)果以管道的形式傳遞給下面的語句,聚合查詢必須使用WITH
RETURN [ORDER BY] [SKIP] [LIMIT] //返回、排序、跳過、返回個數(shù)
插入數(shù)據(jù)進行測試
CREATE (北京市轉(zhuǎn)運中心:OLT {bid: 8001, name: "北京市轉(zhuǎn)運中心", address: "北京市轉(zhuǎn)運中心", location : point({latitude:39.904179, longitude:116.407387})})
CREATE (上海市轉(zhuǎn)運中心:OLT {bid: 8002, name: "上海市轉(zhuǎn)運中心", address: "上海市轉(zhuǎn)運中心", location : point({latitude:31.230525, longitude:121.473667})})
CREATE (南京市轉(zhuǎn)運中心:OLT {bid: 8003, name: "南京市轉(zhuǎn)運中心", address: "南京市轉(zhuǎn)運中心", location : point({latitude:32.059344, longitude:118.796624})})
CREATE (太原市轉(zhuǎn)運中心:OLT {bid: 8004, name: "太原市轉(zhuǎn)運中心", address: "太原市轉(zhuǎn)運中心", location : point({latitude:37.870451, longitude:112.549656})})
CREATE (鄭州市轉(zhuǎn)運中心:OLT {bid: 8005, name: "鄭州市轉(zhuǎn)運中心", address: "鄭州市轉(zhuǎn)運中心", location : point({latitude:34.745551, longitude:113.624321})})
CREATE(北京市轉(zhuǎn)運中心)-[:IN_LINE {cost:10684.9}]->(上海市轉(zhuǎn)運中心),(北京市轉(zhuǎn)運中心)<-[:OUT_LINE {cost:10684.9}]-(上海市轉(zhuǎn)運中心),(北京市轉(zhuǎn)運中心)-[:IN_LINE {cost:8993.1}]->(南京市轉(zhuǎn)運中心),(北京市轉(zhuǎn)運中心)<-[:OUT_LINE {cost:8993.1}]-(南京市轉(zhuǎn)運中心),(南京市轉(zhuǎn)運中心)-[:IN_LINE {cost:2699.4}]->(上海市轉(zhuǎn)運中心),(南京市轉(zhuǎn)運中心)<-[:OUT_LINE {cost:2699.4}]-(上海市轉(zhuǎn)運中心),(太原市轉(zhuǎn)運中心)-[:IN_LINE {cost:3609.7}]->(鄭州市轉(zhuǎn)運中心),(太原市轉(zhuǎn)運中心)<-[:OUT_LINE {cost:3609.7}]-(鄭州市轉(zhuǎn)運中心),(鄭州市轉(zhuǎn)運中心)-[:IN_LINE {cost:5659.7}]->(南京市轉(zhuǎn)運中心),(鄭州市轉(zhuǎn)運中心)<-[:OUT_LINE {cost:5659.7}]-(南京市轉(zhuǎn)運中心)
CREATE (昌平區(qū)轉(zhuǎn)運中心:TLT {bid: 90001, name: "昌平區(qū)轉(zhuǎn)運中心", address: "昌平區(qū)轉(zhuǎn)運中心", location : point({latitude:40.220952, longitude:116.231034})})
CREATE (北京市昌平區(qū)新龍城:AGENCY {bid: 100260, name: "北京市昌平區(qū)新龍城", address: "龍躍苑四區(qū)3號樓底商", phone : "010-53049073,010-53576707", location : point({latitude:40.07544443596149, longitude:116.3470535709328})})
CREATE(北京市昌平區(qū)新龍城)-[:IN_LINE {cost:189.7}]->(昌平區(qū)轉(zhuǎn)運中心),(北京市昌平區(qū)新龍城)<-[:OUT_LINE {cost:189.7}]-(昌平區(qū)轉(zhuǎn)運中心)
CREATE (北京市昌平區(qū)定泗路:AGENCY {bid: 100280, name: "北京市昌平區(qū)定泗路", address: "北七家鎮(zhèn)定泗路蒼龍街交叉口", phone : "010-86392987", location : point({latitude:40.11765281246394, longitude:116.37212849638287})})
CREATE(北京市昌平區(qū)定泗路)-[:IN_LINE {cost:166.2}]->(昌平區(qū)轉(zhuǎn)運中心),(北京市昌平區(qū)定泗路)<-[:OUT_LINE {cost:166.2}]-(昌平區(qū)轉(zhuǎn)運中心)
CREATE (海淀區(qū)轉(zhuǎn)運中心:TLT {bid: 90002, name: "海淀區(qū)轉(zhuǎn)運中心", address: "海淀區(qū)轉(zhuǎn)運中心", location : point({latitude:39.959893, longitude:116.2977})})
CREATE (北京市海淀區(qū)小營:AGENCY {bid: 100347, name: "北京市海淀區(qū)小營", address: "北京市昌平區(qū)回龍觀街道金燕龍大廈停車場", phone : "010-86483817,010-86483817,010-86483817", location : point({latitude:40.06177798692319, longitude:116.32706587559049})})
CREATE(北京市海淀區(qū)小營)-[:IN_LINE {cost:116.1}]->(海淀區(qū)轉(zhuǎn)運中心),(北京市海淀區(qū)小營)<-[:OUT_LINE {cost:116.1}]-(海淀區(qū)轉(zhuǎn)運中心)
CREATE (北京市海淀區(qū)萬泉河:AGENCY {bid: 100227, name: "北京市海淀區(qū)萬泉河", address: "北京市海淀區(qū)四季青鎮(zhèn)杏石口路47號院", phone : "18521852356", location : point({latitude:39.94882822425318, longitude:116.25707017441161})})
CREATE(北京市海淀區(qū)萬泉河)-[:IN_LINE {cost:36.8}]->(海淀區(qū)轉(zhuǎn)運中心),(北京市海淀區(qū)萬泉河)<-[:OUT_LINE {cost:36.8}]-(海淀區(qū)轉(zhuǎn)運中心)
CREATE(昌平區(qū)轉(zhuǎn)運中心)-[:IN_LINE {cost:383.3}]->(北京市轉(zhuǎn)運中心),(昌平區(qū)轉(zhuǎn)運中心)<-[:OUT_LINE {cost:383.3}]-(北京市轉(zhuǎn)運中心),(海淀區(qū)轉(zhuǎn)運中心)-[:IN_LINE {cost:112.3}]->(北京市轉(zhuǎn)運中心),(海淀區(qū)轉(zhuǎn)運中心)<-[:OUT_LINE {cost:112.3}]-(北京市轉(zhuǎn)運中心)
CREATE (浦東新區(qū)轉(zhuǎn)運中心:TLT {bid: 90003, name: "浦東新區(qū)轉(zhuǎn)運中心", address: "浦東新區(qū)轉(zhuǎn)運中心", location : point({latitude:31.221461, longitude:121.544346})})
CREATE (上海市浦東新區(qū)南匯:AGENCY {bid: 210057, name: "上海市浦東新區(qū)南匯", address: "園春路8號", phone : "18821179169", location : point({latitude:31.035240152911637, longitude:121.73459966751048})})
CREATE(上海市浦東新區(qū)南匯)-[:IN_LINE {cost:275.4}]->(浦東新區(qū)轉(zhuǎn)運中心),(上海市浦東新區(qū)南匯)<-[:OUT_LINE {cost:275.4}]-(浦東新區(qū)轉(zhuǎn)運中心)
CREATE (上海市浦東新區(qū)周浦:AGENCY {bid: 210127, name: "上海市浦東新區(qū)周浦", address: "川周公路3278-8號", phone : "021-68060322", location : point({latitude:31.132409729356993, longitude:121.59815370294322})})
CREATE(上海市浦東新區(qū)周浦)-[:IN_LINE {cost:111.6}]->(浦東新區(qū)轉(zhuǎn)運中心),(上海市浦東新區(qū)周浦)<-[:OUT_LINE {cost:111.6}]-(浦東新區(qū)轉(zhuǎn)運中心)
CREATE (奉賢區(qū)轉(zhuǎn)運中心:TLT {bid: 90004, name: "奉賢區(qū)轉(zhuǎn)運中心", address: "奉賢區(qū)轉(zhuǎn)運中心", location : point({latitude:30.918406, longitude:121.473945})})
CREATE (上海市奉賢區(qū)東部:AGENCY {bid: 210017, name: "上海市奉賢區(qū)東部", address: "上上海市奉賢區(qū)洪廟鎮(zhèn)洪蘭路351", phone : "021-57171717", location : point({latitude:30.917752751719863, longitude:121.67587819184698})})
CREATE(上海市奉賢區(qū)東部)-[:IN_LINE {cost:192.9}]->(奉賢區(qū)轉(zhuǎn)運中心),(上海市奉賢區(qū)東部)<-[:OUT_LINE {cost:192.9}]-(奉賢區(qū)轉(zhuǎn)運中心)
CREATE (上海市奉賢區(qū)青村:AGENCY {bid: 210442, name: "上海市奉賢區(qū)青村", address: "姚家村1127號", phone : "021-57566663,021-57566606", location : point({latitude:30.916946897994983, longitude:121.57954144207972})})
CREATE(上海市奉賢區(qū)青村)-[:IN_LINE {cost:100.9}]->(奉賢區(qū)轉(zhuǎn)運中心),(上海市奉賢區(qū)青村)<-[:OUT_LINE {cost:100.9}]-(奉賢區(qū)轉(zhuǎn)運中心)
CREATE(浦東新區(qū)轉(zhuǎn)運中心)-[:IN_LINE {cost:68.0}]->(上海市轉(zhuǎn)運中心),(浦東新區(qū)轉(zhuǎn)運中心)<-[:OUT_LINE {cost:68.0}]-(上海市轉(zhuǎn)運中心),(奉賢區(qū)轉(zhuǎn)運中心)-[:IN_LINE {cost:347.4}]->(上海市轉(zhuǎn)運中心),(奉賢區(qū)轉(zhuǎn)運中心)<-[:OUT_LINE {cost:347.4}]-(上海市轉(zhuǎn)運中心)
CREATE (玄武區(qū)轉(zhuǎn)運中心:TLT {bid: 90004, name: "玄武區(qū)轉(zhuǎn)運中心" , location : point({latitude:32.048644, longitude:118.797779})})
CREATE (江蘇省南京市玄武區(qū)紫金墨香苑:AGENCY {bid: 25073, name: "江蘇省南京市玄武區(qū)紫金墨香苑", address: "棲霞區(qū)燕堯路100號", phone : "025-58765331,025-83241955,025-83241881", location : point({latitude:32.117016089520305, longitude:118.86319310255513})})
CREATE(江蘇省南京市玄武區(qū)紫金墨香苑)-[:IN_LINE {cost:98.0}]->(玄武區(qū)轉(zhuǎn)運中心),(江蘇省南京市玄武區(qū)紫金墨香苑)<-[:OUT_LINE {cost:98.0}]-(玄武區(qū)轉(zhuǎn)運中心)
CREATE (江蘇省南京市玄武區(qū)長江路:AGENCY {bid: 25023, name: "江蘇省南京市玄武區(qū)長江路", address: "觀音閣10號", phone : "18521133265,18695799166", location : point({latitude:32.04803554410631, longitude:118.79190455263355})})
CREATE(江蘇省南京市玄武區(qū)長江路)-[:IN_LINE {cost:5.6}]->(玄武區(qū)轉(zhuǎn)運中心),(江蘇省南京市玄武區(qū)長江路)<-[:OUT_LINE {cost:5.6}]-(玄武區(qū)轉(zhuǎn)運中心)
CREATE(玄武區(qū)轉(zhuǎn)運中心)-[:IN_LINE {cost:12.0}]->(南京市轉(zhuǎn)運中心),(玄武區(qū)轉(zhuǎn)運中心)<-[:OUT_LINE {cost:12.0}]-(南京市轉(zhuǎn)運中心)
CREATE (小店區(qū)轉(zhuǎn)運中心:TLT {bid: 90005, name: "小店區(qū)轉(zhuǎn)運中心" , location : point({latitude:37.736865, longitude:112.565524})})
CREATE (山西省太原市青龍:AGENCY {bid: 351068, name: "山西省太原市青龍", address: "長治路33號經(jīng)典家園停車場內(nèi)13號商鋪", phone : "0351-2025888", location : point({latitude:37.83589608758359, longitude:112.56059258109424})})
CREATE(山西省太原市青龍)-[:IN_LINE {cost:110.3}]->(小店區(qū)轉(zhuǎn)運中心),(山西省太原市青龍)<-[:OUT_LINE {cost:110.3}]-(小店區(qū)轉(zhuǎn)運中心)
CREATE (山西省太原市長風街:AGENCY {bid: 351045, name: "山西省太原市長風街", address: "平陽路104號省農(nóng)機公司院內(nèi)", phone : "18636100730", location : point({latitude:37.809964384001226, longitude:112.55299317699505})})
CREATE(山西省太原市長風街)-[:IN_LINE {cost:82.1}]->(小店區(qū)轉(zhuǎn)運中心),(山西省太原市長風街)<-[:OUT_LINE {cost:82.1}]-(小店區(qū)轉(zhuǎn)運中心)
CREATE(小店區(qū)轉(zhuǎn)運中心)-[:IN_LINE {cost:149.4}]->(太原市轉(zhuǎn)運中心),(小店區(qū)轉(zhuǎn)運中心)<-[:OUT_LINE {cost:149.4}]-(太原市轉(zhuǎn)運中心)
CREATE (中原區(qū)轉(zhuǎn)運中心:TLT {bid: 90006, name: "中原區(qū)轉(zhuǎn)運中心" , location : point({latitude:34.74828, longitude:113.612966})})
CREATE (河南省鄭州市鄭上路:AGENCY {bid: 371067, name: "河南省鄭州市鄭上路", address: "中原西路西四環(huán)西北角", phone : "0371-55116757,0371-68014786", location : point({latitude:34.74753024533005, longitude:113.57428550005442})})
CREATE(河南省鄭州市鄭上路)-[:IN_LINE {cost:35.4}]->(中原區(qū)轉(zhuǎn)運中心),(河南省鄭州市鄭上路)<-[:OUT_LINE {cost:35.4}]-(中原區(qū)轉(zhuǎn)運中心)
CREATE (河南省鄭州市潁河路:AGENCY {bid: 371086, name: "河南省鄭州市潁河路", address: "航海西路與西三環(huán)交叉口向南300米路西中貿(mào)商務", phone : "19139415556", location : point({latitude:34.71593280680163, longitude:113.60398506929064})})
CREATE(河南省鄭州市潁河路)-[:IN_LINE {cost:36.9}]->(中原區(qū)轉(zhuǎn)運中心),(河南省鄭州市潁河路)<-[:OUT_LINE {cost:36.9}]-(中原區(qū)轉(zhuǎn)運中心)
CREATE(中原區(qū)轉(zhuǎn)運中心)-[:IN_LINE {cost:11.5}]->(鄭州市轉(zhuǎn)運中心),(中原區(qū)轉(zhuǎn)運中心)<-[:OUT_LINE {cost:11.5}]-(鄭州市轉(zhuǎn)運中心)
基礎查詢
MATCH (n) RETURN n //查詢所有的數(shù)據(jù),數(shù)據(jù)量大是勿用
MATCH (n:AGENCY) RETURN n //查詢所有的網(wǎng)點(AGENCY)
MATCH (n:OLT {name: "北京市轉(zhuǎn)運中心"}) -- (m) RETURN n,m //查詢所有與“北京市轉(zhuǎn)運中心”有關(guān)系的節(jié)點
MATCH (n:OLT {name:"北京市轉(zhuǎn)運中心"}) --> (m:OLT) RETURN n,m //查詢所有"北京市轉(zhuǎn)運中心"關(guān)聯(lián)的一級轉(zhuǎn)運中心
MATCH (n:OLT {name:"北京市轉(zhuǎn)運中心"}) -[r:IN_LINE]- (m) RETURN n,r,m //可以指定關(guān)系標簽查詢
MATCH p = (n:OLT {name:"北京市轉(zhuǎn)運中心"}) --> (m:OLT) RETURN p //將查詢賦值與變量
//通過 type()函數(shù)查詢關(guān)系類型
MATCH (n:OLT {name:"北京市轉(zhuǎn)運中心"}) -[r]-> (m:OLT {name:"南京市轉(zhuǎn)運中心"}) RETURN type(r)
關(guān)系深度查詢
//查詢【北京市轉(zhuǎn)運中心】關(guān)系中深度為1~2層關(guān)系的節(jié)點
MATCH (n:OLT {name:"北京市轉(zhuǎn)運中心"}) -[*1..2]->(m) RETURN *
//也可以這樣
MATCH (n:OLT {name:"北京市轉(zhuǎn)運中心"}) -[*..2]->(m) RETURN *
//也可以通過變量的方式查詢
MATCH path = (n:OLT {name:"北京市轉(zhuǎn)運中心"}) -[*..2]->(m)
RETURN path
//查詢關(guān)系,relationships()獲取結(jié)果中的關(guān)系,WITH向后傳遞數(shù)據(jù)
MATCH path = (n:OLT {name:"北京市轉(zhuǎn)運中心"}) -[*..2]->(m)
WITH n,m, relationships(path) AS r
RETURN r
//查詢兩個網(wǎng)點之間所有的路線,最大深度為6,可以查詢到2條路線
MATCH path = (n:AGENCY) -[*..6]->(m:AGENCY)
WHERE n.name = "北京市昌平區(qū)定泗路" AND m.name = "上海市浦東新區(qū)南匯"
RETURN path重點:查詢兩地的最最短距離
//查詢兩個網(wǎng)點之間最短路徑,查詢深度最大為10
MATCH path = shortestPath((n:AGENCY) -[*..10]->(m:AGENCY))
WHERE n.name = "北京市昌平區(qū)定泗路" AND m.name = "上海市浦東新區(qū)南匯"
RETURN path//查詢兩個網(wǎng)點之間所有的路線中成本最低的路線,最大深度為10(如果成本相同,轉(zhuǎn)運節(jié)點最少)
MATCH path = (n:AGENCY) -[*..10]->(m:AGENCY)
WHERE n.name = "北京市昌平區(qū)定泗路" AND m.name = "上海市浦東新區(qū)南匯"
UNWIND relationships(path) AS r //unwind將列表變成單獨的一行一行的形式,就類是進行循環(huán)
WITH sum(r.cost) AS cost, path
RETURN path ORDER BY cost ASC, LENGTH(path) ASC LIMIT 1
//UNWIND是將列表數(shù)據(jù)展開操作
//sum()是聚合統(tǒng)計函數(shù),類似還有:avg()、max()、min()等
分頁查詢
//分頁查詢網(wǎng)點,按照bid正序排序,每頁查詢2條數(shù)據(jù),第一頁
MATCH (n:AGENCY)
RETURN n ORDER BY n.bid ASC SKIP 0 LIMIT 2
//第二頁
MATCH (n:AGENCY) skip就是跳過的個數(shù),這里的效果就是查詢第二頁
RETURN n ORDER BY n.bid ASC SKIP 2 LIMIT 2
//……
?3.更新數(shù)據(jù)
// 更新/設置 屬性
MATCH (n:AGENCY {name:"北京市昌平區(qū)新龍城"})
SET n.address = "龍躍苑四區(qū)3號樓底商101號"
RETURN n
//通過remove移除屬性
MATCH (n:AGENCY {name:"北京市昌平區(qū)新龍城"}) REMOVE n.address RETURN n
//沒有address屬性的增加屬性
MATCH (n:AGENCY) WHERE n.address IS NULL SET n.address = "暫無地址" RETURN n
4.刪除數(shù)據(jù)
//刪除節(jié)點
MATCH (n:AGENCY {name:"航頭營業(yè)部"}) DELETE n
//有關(guān)系的節(jié)點是不能直接刪除的
MATCH (n:AGENCY {name:"北京市昌平區(qū)新龍城"}) DELETE n
//刪除節(jié)點和關(guān)系,強制刪除
MATCH (n:AGENCY {name:"北京市昌平區(qū)新龍城"}) DETACH DELETE n
//刪除所有節(jié)點和關(guān)系,慎用!
MATCH (n) DETACH DELETE n
5.索引
// 更新/設置 屬性
MATCH (n:AGENCY {name:"北京市昌平區(qū)新龍城"})
SET n.address = "龍躍苑四區(qū)3號樓底商101號"
RETURN n
//通過remove移除屬性
MATCH (n:AGENCY {name:"北京市昌平區(qū)新龍城"}) REMOVE n.address RETURN n
//沒有address屬性的增加屬性
MATCH (n:AGENCY) WHERE n.address IS NULL SET n.address = "暫無地址" RETURN n
SDN(Spring Data Neo4k)使用
導入依賴
<!--SDN依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-neo4j</artifactId></dependency>
編寫application.yml
server:port: 9902
spring:application:name: sl-express-sdndata:neo4j:database: neo4jneo4j:authentication:username: neo4jpassword: neo4j123uri: neo4j://192.168.150.101:7687 #對應的neo4j的地址
使用SDN提供的Repository
SDN也是遵循了Spring Data JPA規(guī)范,同時也提供了Neo4jRepository,該接口中提供了基本的CRUD操作,我們定義Repository需要繼承該接口,實現(xiàn)類會自動生成并配置到ioc,后續(xù)使用直接從ioc中獲取即可。
我們編寫Repository時只需要繼承Neo4jRepository接口即可,在Neo4jRepository中提供了增刪改查等一系列簡單的操作方法。
實現(xiàn)Neo4jRepository的格式為下:
import com.sl.ms.Entitys.AgencyEntity;
import org.springframework.data.neo4j.repository.Neo4jRepository;/*** 網(wǎng)點操作*/
//Neo4jRepository需要提供: 實體類和Id的類型
public interface AgencyRepository extends Neo4jRepository<AgencyEntity, Long> {}
?Neo4jRepository需要提供: 實體類和Id的類型。
在SDK中只要我們使用符合規(guī)范的名命,SDN就可以自動實現(xiàn)對應的方法(有點類似mybatis-plus)。
對應名字規(guī)范為下:
?
例子為下:
import com.sl.ms.Entitys.AgencyEntity;
import org.springframework.data.neo4j.repository.Neo4jRepository;/*** 網(wǎng)點操作*/
public interface AgencyRepository extends Neo4jRepository<AgencyEntity, Long> {/*** 根據(jù)bid查詢** @param bid 業(yè)務id* @return 網(wǎng)點數(shù)據(jù)*/AgencyEntity findByBid(Long bid);/*** 根據(jù)bid刪除** @param bid 業(yè)務id* @return 刪除的數(shù)據(jù)條數(shù)*/Long deleteByBid(Long bid);
}
進行測試
測試代碼為下:
import com.sl.ms.Entitys.AgencyEntity;
import com.sl.ms.Repository.AgencyRepository;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.*;
import javax.annotation.Resource;
import java.util.List;@SpringBootTest
class AgencyRepositoryTest {@Resourceprivate AgencyRepository agencyRepository;@Testpublic void testSave() {AgencyEntity agencyEntity = new AgencyEntity();agencyEntity.setAddress("測試數(shù)據(jù)地址");agencyEntity.setBid(9001L);agencyEntity.setName("測試節(jié)點");agencyEntity.setPhone("1388888888888");this.agencyRepository.save(agencyEntity);System.out.println(agencyEntity);}
}
測試結(jié)果為下:?
復雜查詢(自定義cql)
例子(就是獲取兩地的最短距離)
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.sl.ms.Entitys.AgencyEntity;
import com.sl.ms.Repository.TransportLineRepository;
import com.sl.ms.dto.OrganDTO;
import com.sl.ms.dto.TransportLineNodeDTO;
import com.sl.ms.enums.OrganTypeEnum;
import org.neo4j.driver.internal.InternalPoint2D;
import org.neo4j.driver.types.Path;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;@Component
public class TransportLineRepositoryImpl implements TransportLineRepository {@Resourceprivate Neo4jClient neo4jClient;/*** 根據(jù)起止網(wǎng)點 查詢轉(zhuǎn)運路線最短的路線信息* @param start 開始網(wǎng)點* @param end 結(jié)束網(wǎng)點* @return*///查詢的CQL語句為: (最好不用進行拼接,直接用一個完整的字符串)
// MATCH path = shortestPath((n:AGENCY) -[*..10]->(m:AGENCY))
// WHERE n.name = "北京市昌平區(qū)定泗路" AND m.name = "上海市浦東新區(qū)南匯"
// RETURN path@Overridepublic TransportLineNodeDTO findShortestPath(AgencyEntity start, AgencyEntity end) {//獲取網(wǎng)點數(shù)據(jù)在Neo4j中的類型,獲取@Node中的屬性值,這樣可以動態(tài)獲取節(jié)點的標簽//這里的標簽有: 一級轉(zhuǎn)運中心,二級轉(zhuǎn)運中心,站點String type = AgencyEntity.class.getAnnotation(Node.class).value()[0];//構(gòu)造CQL 查詢語句String Cql = StrUtil.format("MATCH path = shortestPath((n:{}) -[*..10]->(m:{})) WHERE n.bid=$startId AND m.bid=$endId RETURN path",type, type);//執(zhí)行查詢Optional<TransportLineNodeDTO> one = this.neo4jClient.query(Cql)// 綁定參數(shù), cql中使用$綁定變量.bind(start.getBid()).to("startId").bind(end.getBid()).to("endId")// 設置響應類型,最終返回的類型,這里我們需要返回.fetchAs(TransportLineNodeDTO.class)// mappedBy 設置結(jié)果映射.mappedBy((typeSystem, record) -> {//record中就是查詢的結(jié)果(一條最短路線),獲取第一個參數(shù),也就是path// 獲取0號下標的 Path路徑Path path = record.get(0).asPath();// 創(chuàng)建路線對象 TransportLineNodeDTOTransportLineNodeDTO transportLineNodeDTO = new TransportLineNodeDTO();path.nodes().forEach(node -> {// 遍歷路徑下的所有節(jié)點Map<String, Object> nodeMap = node.asMap();// 將每一個節(jié)點信息封裝成一個OrganDTO// 通過節(jié)點得到參數(shù)map,將map轉(zhuǎn)為OrganDTO tips: BeanUtilOrganDTO organDTO = BeanUtil.toBeanIgnoreError(nodeMap, OrganDTO.class);//此時organDTO中的type和經(jīng)緯度都是null,我們需要為其賦值//標簽會存在多個,這里我們就取第一個String title = CollUtil.getFirst(node.labels());// OrganDTO設置類型: 取Node中第一個標簽作為類型 tips: OrganTypeEnumorganDTO.setType(OrganTypeEnum.valueOf(title).getCode());// OrganDTO設置經(jīng)緯度: 取出經(jīng)緯度 經(jīng)緯度類: InternalPoint2D//從Map中獲取經(jīng)緯度InternalPoint2D location = MapUtil.get(nodeMap, "location", InternalPoint2D.class);organDTO.setLatitude(location.x());//設置緯度,為xorganDTO.setLongitude(location.y());//設置經(jīng)度,為y// 存入到 路線對應的節(jié)點集合中transportLineNodeDTO.getNodeList().add(organDTO);});path.relationships().forEach(relationship -> {// 遍歷路徑下的所有關(guān)系// 將每個路線的成本加一起 得到路線總成本 保留2位小數(shù)Map<String, Object> relationshipMap = relationship.asMap();//獲取成本Double cost = MapUtil.get(relationshipMap, "cost", Double.class);//將成本進行累加transportLineNodeDTO.setCost(transportLineNodeDTO.getCost() + cost);});// 返回路線數(shù)據(jù)return transportLineNodeDTO;}).one();//返回可能會有多個,我們直接取一個即可return one.orElse(null); //不會空時返回數(shù)據(jù),為空時則返回null}
}
進行測試
import com.sl.ms.Entitys.AgencyEntity;
import com.sl.ms.Repository.TransportLineRepository;
import com.sl.ms.dto.TransportLineNodeDTO;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
class TransportLineRepositoryTest {@Resourceprivate TransportLineRepository transportLineRepository;@Testvoid findShortestPath() {AgencyEntity start = AgencyEntity.builder().bid(100280L).build();AgencyEntity end = AgencyEntity.builder().bid(210057L).build();TransportLineNodeDTO transportLineNodeDTO = this.transportLineRepository.findShortestPath(start, end);System.out.println(transportLineNodeDTO);}
}
最終成功獲取到最短的路徑和費用。