标签:# Neo4j

SpringBoot 3.3 + Neo4j 5.1 + Java17 接入教程

官方文档: Spring Data Neo4j 基于官方文档,基本就能完成基本的接入,Neo4j的版本很乱,如果使用SpringBoot2.+的话,一定要注意Neo4j Server的版本与Driver的匹配关系,否则很容易踩坑。 由于我不是生产使用,直接用官方最新反倒是没遇到此类问题,但网上对于这个问题遇到的很多。 简单接入 写了几个单测,看了下流程,得益于SpringBoot-Data的封装,和操作MongoDB、MySQL等关系型数据库基本无异,使用过程很丝滑。 @Test public void readAll() { List<Person> personList = personRepository.findAll(); Assert.isTrue(!personList.isEmpty(), "isEmpty"); } @Test public void delById() { personRepository.findById(71L).ifPresent(person -> { System.out.println("before delete: " + person.getName()); }); personRepository.deleteById(71L); Person person = personRepository.findById(71L).orElse(null); System.out.println("after delete: " + person); } @Test public void save() { Person person = new Person(); person.setName("人参果树"); personRepository.save(person); } findAll delById 删除前: 删除后: saveOne 关系的创建 对于节点的基本查询,由于其结构类似于结构性,和结构性数据库查询无异,但是对于N4o4j特殊的关系结构,就有一些不一样了。 @Repository public interface PersonRepository extends Neo4jRepository<Person, Long> { Person findByName(String name); /** * 创建人物关系 * @param from 源 * @param relation 关系 * @param to 目标 */ @Query("match (n:person {name: $from}),(m:person {name: $to}) " + "create (n)-[:西游人物关系{relation:$relation}]->(m)") void createRelation(String from, String relation, String to); } @SpringBootTest public class PersonRelationShipRepositoryTest { @Resource private PersonRepository personRepository; @Test public void addRelation() { Person personYangjian = personRepository.findByName("杨戬"); Person person2 = new Person(); person2.setName("玉鼎真人"); PersonRelationShip relationShip = new PersonRelationShip(); relationShip.setChild(person2); relationShip.setRelation("师傅"); personYangjian.getPersonRelationShips().add(relationShip); personRepository.save(personYangjian); } @Test public void addRelation2() { personRepository.createRelation("玉皇大帝", "妻子", "王母娘娘"); } } 创建关系第一种方式 创建关系第二种方式 坑 坑1 spring-boot-data 3.+的很多注解都改变了,例如: 在老版本中标注节点使用的是@NodeEntity,新版本被替换为@Node(labels = "person") 在老版本中,关系的表述是在关系对象中通过@RelationshipEntity、@StartNode、@EndNode来描述,在新版这些都没有了。取而代之的是在源对象中补充属性@Relationship(type = "师傅", direction = Relationship.Direction.OUTGOING)来描述关系。 老关系: @Data @RelationshipEntity(type = "xxx") public class PersonRelationShip { @Id @GeneratedValue private Long id; @StartNode private Person parent; @TargetNode private Person child; } 新关系: @Node(labels = "person") @Data public class Person { @Id @GeneratedValue private Long id; @Property private String name; @Relationship(type = "师傅", direction = Relationship.Direction.OUTGOING) private List<PersonRelationShip> personRelationShips; } @Data @RelationshipProperties public class PersonRelationShip { @Id @GeneratedValue private Long id; @TargetNode private Person child; @Property private String relation; } 坑2 spring-boot-data 3.+的@Query中想要获取参数,需要使用 $fieldName,而不是 {0} 的方式,如果自己写的时候一定要注意。比如: /** * 创建人物关系 * @param from 源 * @param relation 关系 * @param to 目标 */ @Query("match (n:person {name: $from}),(m:person {name: $to}) " + "create (n)-[:西游人物关系{relation:$relation}]->(m)") void createRelation(String from, String relation, String to);
Read More ~

Neo4j常用函数

字符串函数 match (n:Lianhuachi) where n.name = '去种田的向凹凸' return n.name,substring(n.name, 0,3) AGGREGATION聚合函数 和普通SQL一致的含义 match (n:Lianhuachi) return count(n),max(n.age),min(n.age),avg(n.age),sum(n.age) 关系函数 match (x)-[n:`莲花池人物关系`]->(y) return id(n),n 备份 Neo4j 官方文档: Backup modes ➜ bin ./neo4j-admin database dump neo4j --to-path=/tmp 2024-06-26 15:24:15.414+0000 INFO [o.n.c.d.DumpCommand] Starting dump of database 'neo4j' Done: 37 files, 2.993MiB processed. 2024-06-26 15:24:19.338+0000 INFO [o.n.c.d.DumpCommand] Dump completed successfully ➜ bin ll /tmp/ |grep "neo4j.dump" -rw-r--r-- 1 imyzt wheel 305K Jun 26 23:24 neo4j.dump 恢复 Neo4j 官方文档: Restore a database dump ➜ bin ./neo4j-admin database load --from-path=/tmp/ neo4j --overwrite-destination=true Done: 37 files, 2.993MiB processed. 可以看到,数据恢复了过来。
Read More ~

Neo常用命令 二

UNIQUE约束 避免重复时使用(姓名、身份证不能重复) 旧版本 create constraint on (n:Lianhuachi) assert n.name is unique 新版本 如果再执行上面的语法时报错,说明你使用的是新版本的Neo4j,变更了命令语法。 create constraint uniq_name for (n:Lianhuachi) require n.name is unique 在加了唯一索引后,可以看到,在添加重复数据时会报错: 删除唯一约束 drop constraint uniq_name 可以看到,在删除之后再进行添加,是可以添加进去的。 create (n:Lianhuachi {name: "我是野农", "field": "test"}) return n match (n:Lianhuachi {name: "我是野农""}) return n distinct去重 和SQL一致,对内容进行去重 match (n:Lianhuachi) return distinct(n.name)
Read More ~

Neo4j 常用命令 一

WHERE 可以类似于SQL的写法来实现,首先通过match将节点查询出来(n,m),然后通过WHERE将数据 match (n:Lianhuachi),(m:Lianhuachi) where n.name = '去种田的向凹凸' and m.name = "向云朵" return id(n),n.name,id(m),m.name match (n:Lianhuachi {name: "去种田的向凹凸"}),(m:Lianhuachi {name: "向云朵"}) return id(n),n.name,id(m),m.name DELETE-删除节点 删除节点(如果节点存在关系时,是无法删除的) match (n: Person {name: "xxx"}) delete n 删除关系 match (n: Person {name: "小红"})-[r]->(m: Person {name: "小明"}) delete r REMOVE-删除属性 首先,在student和person标签创建1一个节点 create (n:student:person {name: "张三", age: 18}) return n 查询节点 MATCH (n:person) where n.name = "张三" RETURN n LIMIT 25 MATCH (n:student) RETURN n LIMIT 25 删除标签中的节点 MATCH (n:person) where n.name = "张三" remove n 删除标签中节点的属性 删除前,age=18 MATCH (n:student) where n.name = "张三" return n 删除后,age无了 MATCH (n:student) where n.name = "张三" remove n.age return n 修改标签中节点的属性 修改后,age回来了 MATCH (n:student) where n.name = "张三" set n.age=18 return n 给榜首增加一个属性 match (n:Lianhuachi {name: "我是野农"}) set n.title = '虾米榜榜首' return n ORDER BY - 排序 补充测试数据 create (n:student {name: "张三", age: 18}),(m:student {name: "李四", age: 22}) return n,m 排序 match (n:student) return id(n), n.name,n.age order by n.age desc id(n) n.name n.age 120 "李四" 22 119 "张三" 18 NULL - NULL属性 查询name属性不为空的节点 match (n:student) where n.name is not null return n.name,n.label n.name n.label "张三" null "李四" null 查询sex属性为空的节点 match (n:student) where n.sex is null return n.name,n.label n.name n.label "张三" null "李四" null 给张三设置sex属性,注意where在前,set在后,和MySQL等相反 match (n:student) where n.name='张三' set n.sex='男' return n.name,n.sex,n.age 查询结果:match (n:student) return n IN - 查询多个 查询name等于张三或李四的人: match (n:student) where n.name in ["张三", "李四"] return n 索引 官方文档 旧版本 创建索引: create index on :节点 (属性) 删除索引: drop index on :节点(属性) 新版本(5或更高版本) 创建索引: 缺省索引名称: CREATE INDEX [index_name(可缺省)] FOR (n:person) ON (n.name) 指定索引名称: create index index_test for (n:person) on (n.name) Added 1 index, completed after 992 ms. 查询所有索引: show indexes id name state populationPercent type entityType labelsOrTypes properties indexProvider owningConstraint lastRead readCount 1 "index_343aff4e" "ONLINE" 100 "LOOKUP" "NODE" null null "token-lookup-1.0" null "2024-05-18T13:26:33.878000000Z" 571 3 "index_a302cc54" "ONLINE" 100 "RANGE" "NODE" ["person"] ["name"] "range-1.0" null null 0 2 "index_f7700477" "ONLINE" 100 "LOOKUP" "RELATIONSHIP" null null "token-lookup-1.0" null "2024-05-10T00:48:00.395000000Z" 67 删除索引: drop index index_a302cc54 Removed 1 index, completed after 5 ms.
Read More ~

使用Neo4j建立莲花池人物关系图(核心人物,简版)

最近关注了沅陵的莲花池,整个村子都是钓鱼佬,人均up主,基本都是沾亲带故的,错综复杂,恰逢正在学习Neo4j,可以借此机会将人物关系通过图谱的方式呈现出来。 人物标签创建 首先将人物关系建立出来,利用create来创建效率实在太低了 ,所以决定采用数据导入的方式。 点击查看莲花池人物详情 去种田的向凹凸 小白兔的胡萝卜甜(冉甜) 向云朵 我是野农 画燕儿 向鹿鸣 路人阿丙X 大明星(冉蜜) 向偶然 荷塘星星 向尘俊 向星言 多肉葡萄肉多多 白叔 播音哥 三叔 丹宝 守山人阿亮 导入数据: load csv from "file:///莲花池人物.csv" as line create (:Lianhuachi {name: line[0]}) 最终效果图: MATCH (n:Lianhuachi) RETURN n LIMIT 25 人物关系标签创建 莲花池人物关系(简版) 小白兔的胡萝卜甜(冉甜),丈夫,去种田的向凹凸 去种田的向凹凸,妻子,小白兔的胡萝卜甜(冉甜) 小白兔的胡萝卜甜(冉甜),女儿,向云朵 去种田的向凹凸,女儿,向云朵 画燕儿,丈夫,我是野农 我是野农,妻子,画燕儿 画燕儿,儿子,向鹿鸣 我是野农,儿子,向鹿鸣 大明星(冉蜜),丈夫,路人阿丙X 路人阿丙X,妻子,大明星(冉蜜) 大明星(冉蜜),女儿,向偶然 路人阿丙X,女儿,向偶然 多肉葡萄肉多多,丈夫,荷塘星星 荷塘星星,妻子,多肉葡萄肉多多 荷塘星星,儿子,向尘俊 多肉葡萄肉多多,儿子,向尘俊 荷塘星星,女儿,向星言 多肉葡萄肉多多,女儿,向星言 向星言,亲哥,向尘俊 向尘俊,亲妹,向星言 荷塘星星,父亲,三叔 三叔,儿子,荷塘星星 荷塘星星,表哥,守山人阿亮 守山人阿亮,表弟,荷塘星星 我是野农,亲弟,路人阿丙X 路人阿丙X,亲哥,我是野农 我是野农,钓友,去种田的向凹凸 去种田的向凹凸,钓友,我是野农 去种田的向凹凸,同村,荷塘星星 我是野农,钓友,荷塘星星 荷塘星星,钓友,我是野农 去种田的向凹凸,同村,荷塘星星 导入数据: load csv from "file:///莲花池人物关系.csv" as line create (n:LianhuachiRelation {from: line[0], relation: line[1], to: line[2]}) return n.from, n.relation, n.to 最终效果: MATCH (n:LianhuachiRelation) RETURN n.from, n.relation, n.to 借助人物关系标签,创建人物关系 match (f:Lianhuachi),(r:LianhuachiRelation),(t:Lianhuachi) where f.name=r.from and t.name=r.to create (f)-[rr:莲花池人物关系 {relation: r.relation}]->(t) return f.name, rr.relation, t.name 最终效果: MATCH p=()-[r:莲花池人物关系]->() RETURN p LIMIT 25 查询人物关系 match (n:Lianhuachi {name: "向云朵"}),(m:LianhuachiRelation) where m.from='向云朵' return n.name, m.relation, m.to 在现有的基础上,补充人物关系 match (n:Lianhuachi{name:"大明星(冉蜜)"}),(m:Lianhuachi{name:"小白兔的胡萝卜甜(冉甜)"}) create (n)-[r:`莲花池人物关系`{relation:"亲姐"}]->(m) match (n:Lianhuachi{name:"大明星(冉蜜)"}),(m:Lianhuachi{name:"小白兔的胡萝卜甜(冉甜)"}) create (m)-[r:`莲花池人物关系`{relation:"亲妹"}]->(n) 删除重建人物关系 MATCH (n:Lianhuachi {name:"去种田的向凹凸"})-[r:`莲花池人物关系` {relation: "钓友"}]->(m:Lianhuachi {name:"我是野农"}) delete r MATCH (n:Lianhuachi {name:"我是野农"})-[r:`莲花池人物关系` {relation: "钓友"}]->(m:Lianhuachi {name:"去种田的向凹凸"}) delete r MATCH (n:Lianhuachi {name:"去种田的向凹凸"}),(m:Lianhuachi {name:"我是野农"}) create (n)-[r2:`莲花池人物关系` {relation: "表哥"}]->(m) create (m)-[r3:`莲花池人物关系` {relation: "表弟"}]->(n) return r2.relation,r3.relation
Read More ~

Neo4j 使用

图数据模型:与关系型数据库使用表格存储数据不同,图数据库通过节点(Node)和关系(Relationship)来表示数据和它们之间的联系。 节点:代表实体,如人、地点、物品等。 关系:定义节点之间的连接,可以有方向和属性。 属性:节点和关系的附加信息,如人的姓名、年龄等。 CREATE (person1:Person {name: 'Alice', age: 30}) CREATE (person2:Person {name: 'Bob', age: 25}) CREATE (person1)-[:KNOWS]->(person2) person1/person2:节点 Person:标签 name/age:属性 KNOWS:关系 导入数据 通过GPT,生成《西游记》的人物关系图和人物名单,案例数据如下: 将文件放置于Neo4j的Home/import目录下,然后执行导入命令: load csv from "file:///西游记.csv" as line create (:xiyouRelation {from:line[1], relation:line[3],to:line[0]}) load csv from "file:///人物.csv" as line create (:person {name:line[0]}) 执行match (person) return person,查看数据: 创建人物和关系 创建人物和关系 创建人物 create (:student {name: '小明'}),(:student {name : '小红'}),(:student {name: '小李'}) 创建人物关系,并且返回人物关系 match (n:student {name: '小明'}),(m:student {name: '小红'}) create (n)-[r:同学]->(m) return n.name,type(r),m.name 显示人物关系 MATCH p=()-[r:`同学`]->() RETURN p LIMIT 25 删除标签 match (n:LianhuachiPerson) detach delete n 删除关系 命令: match (n)-[r:西游人物关系]-(s) delete r 结果: Deleted 18 relationships, completed after 6 ms.
Read More ~