neo4j 图数据库 springboot

一.安装

neo4j社区版在liunx安装部署

https://blog.csdn.net/u013946356/article/details/81736232

二.知识图数据导入

参考:https://notemi.cn/neo4j-import-csv-file-data.html

http://openkg.cn/dataset/ch4masterpieces

放在对应的import文件夹下面

导入数据

bash 复制代码
LOAD CSV  WITH HEADERS FROM "file:///xiyouji.csv" AS line
MERGE (p:person{name:line.head});


LOAD CSV WITH HEADERS FROM "file:///xiyouji.csv" AS line
MERGE (p:person{name:line.tail});


LOAD CSV WITH HEADERS FROM "file:///xiyouji.csv" AS line
match (from:person{name:line.tail}),(to:person{name:line.head})
merge (from)-[r:rel{label:line.label,relation:line.relation}]->(to)

三.neo4j 语法

官网地址:https://neo4j.com/docs/cypher-manual/3.5/clauses/match/

bash 复制代码
创建节点(多次执行,会创建相同的多个节点)

CREATE (john:Person {name: 'John'})
CREATE (joe:Person {name: 'Joe'})
CREATE (steve:Person {name: 'Steve'})
CREATE (sara:Person {name: 'Sara'})
CREATE (maria:Person {name: 'Maria'})
CREATE (john)-[:FRIEND]->(joe)-[:FRIEND]->(steve)
CREATE (john)-[:FRIEND]->(sara)-[:FRIEND]->(maria)


CREATE (adam:User { name: 'Adam' }),(pernilla:User { name: 'Pernilla' }),(david:User { name: 'David'}),
  (adam)-[:FRIEND]->(pernilla),(pernilla)-[:FRIEND]->(david)


多个标签到节点
m:节点名
标签名称:Cinema,Film,Movie,Picture
CREATE (m:Movie:Cinema:Film:Picture)


MERGE 如果节点不存在,会创建,
      如果节点的属性没有跟现有节点匹配上,则会创建新节点
      

CREATE (N0:Person {chauffeurName: 'John Brown', name: 'Charlie Sheen', bornIn: 'New York'})

下面就会创建新的节点
MERGE (charlie { name: 'Charlie Sheen', age: 10 })
RETURN charlie

MERGE (charlie { name: 'Charlie Sheen', age: 20 })
RETURN charlie

下面不会创建新的节点
MERGE (charlie { name: 'Charlie Sheen',bornIn: 'New York'})
RETURN charlie


如果"keanu"节点不存在,则创建节点,设置属性created
如果存,则设置属性lastSeen,多个属性逗号分隔
MERGE (keanu:Person { name: 'Keanu Reeves' })
ON CREATE SET keanu.created = timestamp()
ON MATCH SET keanu.lastSeen = timestamp()
RETURN keanu.name, keanu.created, keanu.lastSeen


MATCH (p:Info) where id (p)=195  
MATCH (n:Info) where id (n)=196 
MERGE (p)-[r:HAVE]->(n)
RETURN r


查询

查询所有
MATCH (n)
RETURN n

符号 -- 表示与关系相关,而不考虑关系的类型或方向
MATCH (:Person { name: 'Oliver Stone' })--(movie:Movie)
RETURN movie.title

等价于返回节点和关系
MATCH p =(actor { name: 'Charlie Sheen' })-[:ACTED_IN*2]-(co_actor)
RETURN relationships(p)

查询两个点的单个最短路径
MATCH (start:Person {name: 'Charlie Sheen'}), (end:Person {name: 'Michael Douglas'})
MATCH path = shortestPath((start)-[*]-(end))
RETURN path

All shortest paths 所有最短路径
MATCH (martin:Person { name: 'Martin Sheen' }),(michael:Person { name: 'Michael Douglas' }), p = allShortestPaths((martin)-[*]-(michael))
RETURN p

查询多关系的
MATCH (wallstreet { title: 'Wall Street' })<-[:ACTED_IN|:DIRECTED]-(person)
RETURN person.name

查朋友的朋友
MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof)
RETURN john.name, fof.name


匹配他们的朋友,并仅返回那些具有以"S"开头的"name"属性的关注用户
MATCH (user)-[:FRIEND]->(follower)
WHERE user.name IN ['Joe', 'John', 'Sara', 'Maria', 'Steve'] AND follower.name =~ 'S.*'
RETURN user.name, follower.name


找到朋友数大于1的
MATCH (n {name: 'John'})-[:FRIEND]-(friend)
WITH n, count(friend) AS friendsCount
WHERE friendsCount > 1
RETURN n, friendsCount



查询叫Maria的人是哪一层关系
MATCH (me:Person {name: 'John'})-[:FRIEND*1..3]-(friend:Person {name: 'Maria'})
RETURN CASE
  WHEN size((me)-[:FRIEND]-(friend)) > 0 THEN 'Friend'
  WHEN size((me)-[:FRIEND]-()-[:FRIEND]-(friend)) > 0 THEN 'Friend of Friend'
  WHEN size((me)-[:FRIEND]-()-[:FRIEND]-()-[:FRIEND]-(friend)) > 0 THEN 'Friend of Friend of Friend'
  ELSE 'Not Connected'
END AS relationship


拼接属性[]来查询,过滤动态计算的节点属性
CREATE (a:Restaurant { name: 'Hungry Jo', rating_hygiene: 10, rating_food: 7 }),(b:Restaurant { name: 'Buttercup Tea Rooms', rating_hygiene: 5, rating_food: 6 }),(c1:Category { name: 'hygiene' }),(c2:Category { name: 'food' })
WITH a, b, c1, c2
MATCH (restaurant:Restaurant),(category:Category)
WHERE restaurant["rating_" + category.name]> 6
RETURN DISTINCT restaurant.name


UNWIND关键字用于展开列表或集合中的元素
WITH关键字用于将查询结果传递给下一个查询子句,它类似于SQL中的SELECT子句,可以用于选择和重命名列、聚合、排序等操作

WITH ['John', 'Mark', 'Jonathan', 'Bill'] AS somenames
UNWIND somenames AS names
WITH names AS candidate
WHERE candidate STARTS WITH 'Jo'
RETURN candidate


方括号将从起始索引 1 提取元素,直到(但不包括)结束索引 3
WITH ['Anne', 'John', 'Bill', 'Diane', 'Eve'] AS names
RETURN names[1..3] AS result


从'Anders'开始,找到所有匹配的节点,按名称降序排列并获得顶部结果,
然后找到与该顶部结果连接的所有节点,并返回它们的名称。
MATCH (n { name: 'Anders' })--(m)
WITH m
ORDER BY m.name DESC LIMIT 1
MATCH (m)--(o)
RETURN o.name


使用 exists() 函数仅包含存在属性的节点或关系。
MATCH (n)
WHERE exists(n.belt)
RETURN n.name, n.belt


使用 STARTS WITH 进行前缀字符串搜索
使用 ENDS WITH 进行后缀字符串搜索
使用 CONTAINS 进行子字符串搜索
MATCH (n)
WHERE n.name STARTS WITH 'Pet'
RETURN n.name, n.age

不以'y'结尾
MATCH (n)
WHERE NOT n.name ENDS WITH 'y'
RETURN n.name, n.age

使用正则表达式进行匹配
不区分大小写的正则表达式
MATCH (n)
WHERE n.name =~ '(?i)Tim.*'
RETURN n.name, n.age


排序,跳过,限制
MATCH (n)
RETURN n.name
ORDER BY n.name desc
SKIP 1
LIMIT 2

MATCH (e:Employee) 
WHERE e.id IS NOT NULL
RETURN e.id,e.name,e.sal,e.deptno


MATCH (e:Employee) 
WHERE e.id IN [123,124]
RETURN e.id,SUBSTRING(e.name,0,4),e.sal,e.deptno

MATCH (e:Employee) 
RETURN SUM(e.sal),AVG(e.sal)


关系
最小长度为 3,最大长度为 5。它描述了 4 个节点和 3 个关系、5 个节点和 4 个关系或 6 个节点和 5 个关系的图,所有这些都在一条路径中连接在一起。
(a)-[*3..5]->(b)

(a)-[*3..]->(b)
(a)-[*..5]->(b)
任意长度的路径
(a)-[*]->(b)

MATCH (e:Customer),(cc:CreditCard) 
CREATE (e)-[r:DO_SHOPPING_WITH ]->(cc)


如果节点之间没有KNOWS关系则创建
MATCH (charlie:Person { name: 'Charlie Sheen' }),(oliver:Person { name: 'Oliver Stone' })
MERGE (charlie)-[r:KNOWS]-(oliver)
RETURN r


存在的点,创建带属性的关系
MATCH (cust:Info),(cc:OneId) 
where Id(cust)=152 and Id(cc)= 98
CREATE (cust)-[r:one_with{createTime:"2023-08-14",priority:1,uid:"111",delete:0}]->(cc) 
RETURN r



复制节点关系,删除原有节点关系
MATCH (a:Info)-[r:one_with]->(b:OneId)
WHERE Id(a)=152 and Id(b)= 98
WITH a, b, r
MATCH (c:OneId)
WHERE Id(c)= 170
CREATE (a)-[newR:one_with]->(c)
SET newR = r
DELETE r
RETURN a, c,newR


双向关联
MATCH (a:Node {name: 'A'})
MATCH (b:Node {name: 'B'})
CREATE (a)-[:RELATIONSHIP_TYPE]->(b), (b)-[:RELATIONSHIP_TYPE]->(a)

新增节点和关系

MATCH (fb1:FaceBookProfile1)-[like:LIKES]->(fb2:FaceBookProfile2) 
RETURN like

CREATE (video1:YoutubeVideo1{title:"Action Movie1",updated_by:"Abc",uploaded_date:"10/10/2010"})
-[movie:ACTION_MOVIES{rating:1}]->
(video2:YoutubeVideo2{title:"Action Movie2",updated_by:"Xyz",uploaded_date:"12/12/2012"}) 


查询关系

MATCH (cust)-[r:DO_SHOPPING_WITH]->(cc) 
RETURN cust,cc



删除所有节点和关系
MATCH (n)
DETACH DELETE n

DELETE操作用于删除节点和关联关系
删除节点

MATCH (start)-[r:HAVE]->(end) where id(r)=152 DELETE r

删除关系和节点(多条关键全删)
MATCH (cc: CreditCard)-[rel]-(c:Customer) 
DELETE rel,cc,c


REMOVE操作用于删除标签和属性。
删除属性
match(c:Book) where c.id=122 REMOVE c.price  return c

删除标签
MATCH (n { name: 'David' })
REMOVE  n:person:gay
RETURN n.name, labels(n) AS labels



set添加属性和修改属性值

MATCH (book:Book)
SET book.title = 'superstar',book.price=100
RETURN book

+= 增加修改属性
CREATE (a:Person { name: 'Jane', age: 20 })
WITH a
MATCH (p:Person { name: 'Jane' })
SET p += { name: 'Ellen', livesIn: 'London' }
RETURN p.name, p.age, p.livesIn

MATCH (n {name: 'John'})-[:FRIEND]-(friend)
WITH n, count(friend) AS friendsCount
SET n.friendsCount = friendsCount
RETURN n.friendsCount

增加多个标签
MATCH (n { name: 'David' })
SET n:person:gay
RETURN n.name, labels(n) AS labels

FOREACH
从A节点到D节点的路径上都增加一个属性
MATCH p =(begin)-[*]->(END )
WHERE begin.name = 'A' AND END .name = 'D'
FOREACH (n IN nodes(p)| SET n.marked = TRUE )

UNION合并
需要加 as 别名 保持一致,不然报错

MATCH (cc:CreditCard) RETURN cc.id as id,cc.number as number
UNION
MATCH (dc:DebitCard) RETURN dc.id as id ,dc.number as number



ID和TYPE关系函数来检索关系的Id和类型详细信息。
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ID(movie),TYPE(movie)


它用于知道关系的开始节点。
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN STARTNODE(movie)

它用于知道关系的结束节点。
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ENDNODE(movie)



创建索引(相同标签名称的所有节点的属性创建索引)
CREATE INDEX ON :Customer (name)


删除索引

DROP INDEX ON :Customer (name)



唯一索引
CREATE CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE


删除唯一索引

DROP CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE



UNWIND [{key: 'key1', val: 'val1', insert: true, priority: 'priority1'}, {key: 'key2', val: 'val2', insert: true, priority: 'priority2'}] AS data
MERGE (n:Label {key: data.key, val: data.val})
ON CREATE SET n.insert = data.insert, n.priority = data.priority
RETURN n

WITH ['John', 'Mark', 'Jonathan', 'Bill'] AS names
WITH names AS candidate
WHERE candidate STARTS WITH 'Jo'
RETURN candidate



导入数据
LOAD CSV  WITH HEADERS FROM "file:///xiyouji.csv" AS line
MERGE (p:person{name:line.head});


LOAD CSV WITH HEADERS FROM "file:///xiyouji.csv" AS line
MERGE (p:person{name:line.tail});


LOAD CSV WITH HEADERS FROM "file:///xiyouji.csv" AS line
match (from:person{name:line.tail}),(to:person{name:line.head})
merge (from)-[r:rel{label:line.label,relation:line.relation}]->(to)


UNWIND $rows as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId WITH row,startNode 
										MATCH (endNode) WHERE ID(endNode) = row.endNodeId 
CREATE (startNode)-[rel:`one_with`]->(endNode) SET rel += row.props RETURN row.relRef as ref, ID(rel) as id, $type as type with params {type=rel, rows=[{startNodeId=177, relRef=-12, endNodeId=176, props={uid=646257b2-cfed-4e14-aa43-88e2af0d0ea5, createTime=2023-08-17 09 59 53, priority=0, delete=0}}]}

四.举例

UNWIND 将列表里的值展开

bash 复制代码
CREATE (N0:Person {name: 'Anders'})
CREATE (N1:Person {name: 'Becky'})
CREATE (N2:Person {name: 'Cesar'})
CREATE (N3:Person {name: 'Dilshad'})
CREATE (N4:Person {name: 'George'})
CREATE (N5:Person {name: 'Filipa'})

CREATE (N0)-[:KNOWS]->(N3)
CREATE (N0)-[:KNOWS]->(N2)
CREATE (N0)-[:KNOWS]->(N1)
CREATE (N1)-[:KNOWS]->(N4)
CREATE (N2)-[:KNOWS]->(N4)
CREATE (N3)-[:KNOWS]->(N5)
bash 复制代码
MATCH (me)-[:KNOWS*1..2]-(remote_friend)
WHERE me.name = 'Filipa'
RETURN remote_friend.name

请注意,可变长度关系不能与 CREATE 和 MERGE 一起使用

五. 与springboot 整合

下面实现了Neo4j Spring动态起始节点类型

https://www.codeleading.com/article/35872569441/

举例:

自定义Cypher语句

java 复制代码
public interface OneDynamicRepository extends Neo4jRepository<OneDynamic, Long> {

    @Query("MATCH (startNode:Info) where Id(startNode)=$startId  MATCH (endNode:OneId) where Id(endNode)=$endId  MERGE (startNode)-[r:one_with{ priority: $priority, type:$type ,uid:$uid , delete:0 } ]->(endNode) RETURN r,startNode,endNode ")
    List<OneDynamic> mergeRelationship(@Param("startId") Long startId, @Param("endId") Long endId , @Param("priority") Integer priority,@Param("type") String type,@Param("uid") String uid);
}
相关推荐
这孩子叫逆4 分钟前
Spring Boot项目的创建与使用
java·spring boot·后端
星星法术嗲人8 分钟前
【Java】—— 集合框架:Collections工具类的使用
java·开发语言
一丝晨光26 分钟前
C++、Ruby和JavaScript
java·开发语言·javascript·c++·python·c·ruby
天上掉下来个程小白29 分钟前
Stream流的中间方法
java·开发语言·windows
xujinwei_gingko40 分钟前
JAVA基础面试题汇总(持续更新)
java·开发语言
liuyang-neu41 分钟前
力扣 简单 110.平衡二叉树
java·算法·leetcode·深度优先
Wang's Blog1 小时前
Redis: 集群环境搭建,集群状态检查,分析主从日志,查看集群信息
数据库·redis
一丝晨光1 小时前
Java、PHP、ASP、JSP、Kotlin、.NET、Go
java·kotlin·go·php·.net·jsp·asp
罗曼蒂克在消亡1 小时前
2.3MyBatis——插件机制
java·mybatis·源码学习
_GR1 小时前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划