一.安装
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);
}