neo4j 图数据库 springboot集成

1.springboot集成工程 ermp.neo4j
1 引入pom

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>3.2.10</version>
</dependency>

2 配置直接采用driver驱动版本,采用bolt方式进行连接

配置文件:

spring.data.neo4j.uri=bolt+routing://168.63.118.1:7687
spring.data.neo4j.uris=bolt+routing://168.63.118.2:7687,bolt+routing://168.63.118.3:7687

spring.data.neo4j.username=ermp
spring.data.neo4j.password=ermp_2020_ZNFK
spring.data.neo4j.blotUri=bolt://168.63.118.1


采用一主两从的数据存储结构配置

3 将dirver驱动交给spring管理

@Value("${spring.data.neo4j.blotUri}")
private String uri;

@Value("${spring.data.neo4j.username}")
private String username;

@Value("${spring.data.neo4j.password}")
private String password;


@Bean
public Driver createDriver() {
Config config =getConfig(ServerAddress.of( "168.63.118.1", 7687 ),
ServerAddress.of( "168.63.118.2", 7687 ), ServerAddress.of( "168.63.118.3", 7687 ));
return GraphDatabase.driver( uri, AuthTokens.basic( username, password ), config );
}

private Config getConfig(ServerAddress...addresses){
return Config.builder().withResolver(address -> new HashSet<>( Arrays.asList( addresses ) ) ).build();
}

 


2 数据增删改


neo4j提供了几种数据写法。

 

1 简单的数据连接:


@Autowired
private Driver driver;


@Test
public void test_1(){
demoService.demoQuery();
}


@Test
public void test_2(){
List<Record> list = driver.session().run("match(stu:Student) return (stu)").list();
list.forEach(o-> System.out.println(o.asMap().get("stu")));
}

直接以驱动写入cypher语句的方式进行对库的操作,#{}可传入参数。

 

 

2 封装式写法 --类似jpa(推荐):


@Repository
public interface UserRepository extends Neo4jRepository<UserNode,Long> {

@Query("MATCH (n) WHERE id(n) = :#{#userNode.nodeId} SET n.name = :#{#userNode.name},n.age = :#{#userNode.age},n.sex = :#{#userNode.sex} RETURN n")
UserNode updateByNode(@Param("userNode") UserNode userNode);

}


@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserRepository userRepository;

@Autowired
private KnowRepository knowRepository;

@Override
public UserNode create(UserNode userNode) {
return userRepository.save(userNode);
}

@Override
public void deleteById(Long id) {
userRepository.deleteById(id);
}

@Override
public void deleteAll() {
userRepository.deleteAll();
}

@Override
public Optional<UserNode> findById(long id) {
return userRepository.findById(id);
}

@Override
public List<UserNode> findByName(String name) {
Iterator<UserNode> iterator = userRepository.findAll().iterator();
return IteratorUtils.toList(iterator);
}

@Override
public List<UserNode> findAll() {
return (List<UserNode>) userRepository.findAll();
}

@Override

public Know addIKnows(UserNode fromNode, UserNode toNode) {

Know newKnow = new Know(fromNode,toNode);

return knowRepository.save(newKnow);

}

@Override

public UserNode updateByNode(UserNode userNode) {

return userRepository.updateByNode(userNode);

}

@Override

public void deleteKnowByNodeId(long fromId, long toId) {

knowRepository.deleteByNodeId(fromId,toId);

}

关系映射绑定:Relationship--RelationshipEntity 两个注解的映射

/*注意这个地方:并不是说加了这个注解,然后下面实现了addKnows这个方法在以后调用addKnows

就可以实现关系的增加,这是不对的,我看了很多教程没有说明。这个addKnows方法,只有在节点未被

添加之前,调用该方法添加关系,然后再调用UserService中的create方法,这样关系才会同时被添加到图

数据库中。如果想实现两个已有节点之间增加关系,需要单独实现*/

@Relationship(type = "xing" ,direction = Relationship.OUTGOING)
private Set<UserNode> knows = new HashSet<>();

 

@RelationshipEntity(type = "know")
@Data
public class Know {

@Id
@GeneratedValue
private Long id;

@StartNode
private UserNode from;

@EndNode
private UserNode to;

public Know(UserNode from, UserNode to) {

this.from = from;

this.to = to;

}

}

这样就可以完成java对neo4j的所有操作。

 

3 关系效率
@Test
public void addUserNode3() {
long currentTimeMillis = System.currentTimeMillis();
/*ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS
, new ArrayBlockingQueue(40));
threadPoolExecutor.execute(new UserTestThread());*/

for(int i=1;i<10000;i++){

UserNode userNode3=new UserNode();
userNode3.setAge(18+i);
userNode3.setKnows(null);
userNode3.setName("张三"+i);
userNode3.setSex("男");
userService.create(userNode3);


UserNode userNode=new UserNode();
userNode.setAge(18+i);
userNode.setKnows(null);
userNode.setName("李四"+i);

List<UserNode> byName = userService.findByName("张三" + (i - 1));
Set<UserNode> userNodes = new HashSet<>(byName);

userNode.setKnows(userNodes);
userNode.setSex("男");
UserNode userNode1 = userService.create(userNode);
log.info("userNode1:{}",userNode1);
userNodes.forEach(o->userService.addIKnows(o, userNode1));
}
long currentTimeMillis2 = System.currentTimeMillis();
log.info("共耗时 ==== {}",currentTimeMillis2-currentTimeMillis);

}

插入一万条数据,耗时122s,大概一秒一千条。
这种测试效率有点不准确。

4 实施方案

项目初始化时间需要很长:
csv导入不如neo4j-import
但neo4j-import初始化步骤有些复杂,需要谨慎使用

 

将事实和关系单独插入,先插事实元素,对应关系映射单独写。
实施作业前需要数据清洗(很重要)

posted @ 2020-11-16 16:36  kirsSun  阅读(466)  评论(0)    收藏  举报