Spring-Boot+Neo4j☞节点关系的创建和查询
一、项目目录结构图
二、pom
4.0.0 com.appleyk Spring-Boot-Neo4j 0.0.1-SNAPSHOT Spring-Boot 集成 Neo4j图形数据库实现关系的构建与查询 org.springframework.boot spring-boot-starter-parent 1.5.12.RELEASE 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools true org.springframework.boot spring-boot-starter-test test junit junit org.springframework.boot spring-boot-starter-data-neo4j
三、配置文件
server.port=8080
server.session.timeout=10
server.tomcat.uri-encoding=utf8#在application.properties文件中引入日志配置文件
#===================================== log =============================
logging.config=classpath:logback-boot.xml#Neo4j配置
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=n123
#数据库uri地址
spring.data.neo4j.uri=http://localhost:7474
Application.java
package com.appleyk;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;@SpringBootApplication// same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application extends SpringBootServletInitializer{public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(Application.class);}
}
四、节点实体类
package com.appleyk.node;import org.neo4j.ogm.annotation.GraphId;import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public abstract class BaseNode {@GraphIdprivate Long id;protected String name;public BaseNode() {}public String getName() {return name;}public void setName(String name) {this.name = name;}}
(2)子类:User.java
package com.appleyk.node;import java.util.ArrayList;
import java.util.List;import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;import com.appleyk.relation.LikeRelation;@NodeEntity
public class User extends BaseNode{/*** 用户ID*/private Long uid;/*** 用户性别*/private String sex;/*** 用户年龄*/private Integer age;/*** 兴趣爱好*/private List hobbies;/*** 添加关系喜欢,方向为 ->,表明当前节点是startNode*/@Relationship(type="Like",direction = Relationship.OUTGOING)private List likes;public User(){hobbies = new ArrayList<>();likes = new ArrayList<>();}public Long getUid() {return uid;}public void setUid(Long uid) {this.uid = uid;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public List getHobbies() {return hobbies;}public void setHobbies(List hobbies) {this.hobbies = hobbies;}public void addHobby(String hobby){hobbies.add(hobby);}public void addLikes(User user,String reason,Integer since,Integer relationID){LikeRelation like = new LikeRelation(this, user, reason, since, relationID);this.likes.add(like);}
}
五、关系实体类
LikeRelation.java
package com.appleyk.relation;import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;import com.appleyk.node.BaseNode;@RelationshipEntity(type = "Like")
public class LikeRelation {@GraphIdprivate Long id;/*** 定义关系的起始节点 == StartNode*/@StartNodeprivate BaseNode startNode;/*** 定义关系的终止节点 == EndNode*/@EndNodeprivate BaseNode endNode;/*** 定义关系的属性*/@Property(name = "reason")private String reason;@Property(name = "since")private Integer since;@Property(name = "relationID")private Integer relationID;public LikeRelation() {}public LikeRelation(BaseNode startNode,BaseNode endNode,String reason,Integer since,Integer relationID){this.startNode = startNode;this.endNode = endNode;this.reason = reason;this.since = since;this.relationID = relationID;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public BaseNode getStartNode() {return startNode;}public void setStartNode(BaseNode startNode) {this.startNode = startNode;}public BaseNode getEndNode() {return endNode;}public void setEndNode(BaseNode endNode) {this.endNode = endNode;}public String getReason() {return reason;}public void setReason(String reason) {this.reason = reason;}public Integer getSince() {return since;}public void setSince(Integer since) {this.since = since;}public Integer getRelationID() {return relationID;}public void setRelationID(Integer relationID) {this.relationID = relationID;}}
六、节点User接口
UserRepository.java
package com.appleyk.repository;import java.util.List;import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;import com.appleyk.node.User;@Repository
public interface UserRepository extends GraphRepository{List getUsersByName(@Param("name") String name);/*** 根据年龄查询用户节点* @param age* @return*/@Query("match(n:User) where n.age >{age} return n")List getUsers(@Param("age") Integer age);
}
七、关系Like接口
LikeRelationRepository.java
package com.appleyk.repository;import java.util.List;import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;import com.appleyk.relation.LikeRelation;public interface LikeRelationRepository extends GraphRepository{/*** 查询关系* @param relationName* @return*/@Query("match p = (n)-[r:Like]->(b) return p")List getLikes();/*** 为两个已经存在的节点添加关系* @param startNodeID -- 起始节点* @param endNodeID -- 终止节点* @param rID -- 关系的ID* @param year -- 关系的开始年限* @param reason -- 关系产生的原因* @return*/@Query("match(a),(b) where a.uid={0} and b.uid = {1}"+ " create p = (a)-[r:Like{relationID:{2},since:{3},reason:{4}}]->(b) return p ")List createLikes(Long startNodeID,Long endNodeID,Integer rID,Integer year,String reason);
}
八、neo4j查询关系语句
例如:match p =(n)-[r:Like]-(b) return p
九、单元测试User节点的创建和查询
UserNodeTest.java
import java.util.ArrayList;
import java.util.List;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.appleyk.Application;
import com.appleyk.node.User;
import com.appleyk.relation.LikeRelation;
import com.appleyk.repository.UserRepository;@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=Application.class)
public class UserNodeTest {@AutowiredUserRepository userRepository;/*** 创建用户节点 【批量创建】 * @throws Exception*/@Testpublic void createUser() throws Exception{ List userNodes = new ArrayList<>(); User userNode1 = new User();userNode1.setUid(1001L);userNode1.setName("刘大壮");userNode1.setAge(22);userNode1.setSex("男");userNode1.addHobby("游戏");userNode1.addHobby("睡觉");userNode1.addHobby("撸串");User userNode2 = new User();userNode2.setUid(1002L);userNode2.setName("马晓丽");userNode2.setAge(17);userNode2.setSex("女");userNode2.addHobby("逛街");userNode2.addHobby("美食");userNode2.addHobby("化妆");userNodes.add(userNode1);userNodes.add(userNode2); Iterable iterable = userRepository.save(userNodes); for (User user : iterable) {System.out.println("创建节点:【"+user.getName()+"】成功!");}}/*** 创建节点 == 内置关系*/@Testpublic void createNodeandRelation(){User startNode = new User();startNode.setUid(1011L);startNode.setName("刘泽");startNode.setAge(22);startNode.setSex("男");startNode.addHobby("游戏");startNode.addHobby("睡觉");User endNode1 = new User();endNode1.setUid(1012L);endNode1.setName("张婷");endNode1.setAge(17);endNode1.setSex("女");endNode1.addHobby("逛街");endNode1.addHobby("美食");endNode1.addHobby("化妆");User endNode2 = new User();endNode2.setUid(1013L);endNode2.setName("林志玲");endNode2.setAge(45);endNode2.setSex("女");endNode2.addHobby("逛街");endNode2.addHobby("美食");endNode2.addHobby("化妆");startNode.addLikes(endNode1, "心地善良,人美", 2015,521 );startNode.addLikes(endNode2, "女神姐姐", 2011, 520);User userNode = userRepository.save(startNode);System.out.println("节点"+userNode.getName()+"创建成功!");}/*** 根据用户的name查询user节点列表*/@Testpublic void findUserByName(){List users = userRepository.getUsersByName("刘大壮");System.out.println("共查出来节点有:"+users.size()+"个");}/*** 根据用户的年龄查询user节点【年龄大于18】*/@Testpublic void findUserByAge(){List users = userRepository.getUsers(18);for (User user : users) {System.out.println("共查出来节点有:"+users.size()+"个, == "+user.getName());}}
}
十、单元测试Like关系的创建与查询
关系的添加语句:
match(a),(b) where a.uid = 1001 and b.uid = 1002
create p=(a)-[r:Like{relationID:520,since:2018,reason:'晓丽是女神'}]->(b) return p
LikeRelationTest.java
import java.util.List;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.appleyk.Application;
import com.appleyk.node.User;
import com.appleyk.relation.LikeRelation;
import com.appleyk.repository.LikeRelationRepository;@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class LikeRelationTest {@Autowiredprivate LikeRelationRepository likeRepository;/*** 在已有的两个节点的基础上创建关系*/@Testpublic void createLikeRelation() throws Exception {LikeRelation like = new LikeRelation();/*** 节点 == 刘大壮*/User startNode = new User();startNode.setUid(1001L);/*** 节点 == 马晓丽*/User endNode = new User();endNode.setUid(1002L);like.setStartNode(startNode);like.setEndNode(endNode);like.setRelationID(520);like.setSince(2018);like.setReason("晓丽是女神");List likes = likeRepository.createLikes(startNode.getUid(), endNode.getUid(), like.getRelationID(),like.getSince(),like.getReason()); /*** 遍历创建的关系*/for (LikeRelation likeRelation : likes) {User sNode = (User) likeRelation.getStartNode();User eNode = (User) likeRelation.getEndNode();System.out.println(sNode.getName() + "--喜欢-->" + eNode.getName());}}/*** 创建节点并创建关系*/@Testpublic void createLikes(){LikeRelation like = new LikeRelation();/*** 节点 == 韩梅梅*/User startNode = new User();startNode.setUid(1003L);startNode.setName("韩梅梅");startNode.setAge(18);startNode.setSex("女");startNode.addHobby("看书");startNode.addHobby("逛街");/*** 节点 == 李晓明*/User endNode = new User();endNode.setUid(1004L);endNode.setName("李晓明");endNode.setAge(19);endNode.setSex("男");endNode.addHobby("游戏");endNode.addHobby("音乐");endNode.addHobby("篮球");like.setStartNode(startNode);like.setEndNode(endNode);like.setRelationID(520);like.setSince(2018);like.setReason("晓明好帅啊");LikeRelation relation = likeRepository.save(like);System.out.println(relation.getStartNode().getName()+"-->喜欢"+relation.getEndNode().getName()+",理由:"+relation.getReason());}/*** 查询关系*/@Testpublic void findLikes(){List likes = likeRepository.getLikes();for (LikeRelation likeRelation : likes) {User sNode = (User) likeRelation.getStartNode();User eNode = (User) likeRelation.getEndNode();System.out.println(sNode.getName() + "--喜欢-->" + eNode.getName()+" == reason: "+likeRelation.getReason());}}}
十一、效果演示
创建前清空测试数据的cypher语句:match(n)-[r:Like]-(b) delete n,r,b
(1)创建节点 == 不内置关系
(2)查询年龄大于18岁的user节点
(3)创建节点 == 内置关系的创建
(4)刘大壮喜欢马晓丽,我们为这两个节点创建Like关系,并连带关系的属性一起创建
(5)再创建一个关系,创建关系的同时,创建关系中的startNode和endNode
(6)查询关系Like
十二、项目地址
博主注:neo4j关系其实就是由两个node加一个边edge组成的,关系是有向的,因此,node分起始startNode和终止endNode,通俗点就是源节点到目标节点之间存在一条边,这个边就是关系relation,其查询cypher语句的模板为:
match path =(a)-[r] - (b) return path
在neo4j的关系查询中,关系默认是不区分方向的,因为a和b存在关系r,反过来b和a之间理论上也是存在关系的,除非你指定关系的方向,否则查询的时候会出现正反两条结果,但是显示关系【可视化】的时候,却是有方向的
比如查询语句:match path =(a)-[:Like] -> (b) return path 的结果为:
如果不指定关系的方向查询的话,其语句:match path =(a)-[:Like] - (b) return path 的结果为:
由于demo中我们在定义关系实体的时候,指定了startNode和endNode,这就表明,即使查询语句不指定关系,但是在结果返回的时候,匹配节点的时候,还是会隐式的暴露关系的方向
GitHub地址:Spring-Boot 集成 Neo4j图形数据库实现关系的构建与查询
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
