docker pull neo4j
docker run -d --name myneo4j \
-p 7474:7474 -p 7687:7687 \
-v /home/neo4j/data:/data \
-v /home/neo4j/logs:/logs \
-v /home/neo4j/conf:/var/lib/neo4j/conf \
-v /home/neo4j/import:/var/lib/neo4j/import \
--env NEO4J_AUTH=neo4j/meiya \
neo4j
如果不设置密码,那么默认密码是 neo4j/neo4j
而,不需要验证,则是配置--env NEO4J_AUTH=none
version: "3"
services:
my-neo4j:
image: neo4j:latest
ports:
- 7474:7474
- 7687:7687
volumes:
- /home/neo4j/data:/data
- /home/neo4j/logs:/logs
- /home/neo4j/conf:/var/lib/neo4j/conf
- /home/neo4j/import:/var/lib/neo4j/import
environment:
NEO4J_AUTH: neo4j/meiya@neo4j
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
首先neo4j的事务和mysql的不一样,需要手动配置: 比如下面这个(只是比如,下面的例子在某种程度上是对的,还是不对)
@Configuration
@EnableNeo4jRepositories("com.lry.jps.repository.neo4j")
public class Neo4jConfig {
@Autowired
private SessionFactory sessionFactory;
@Bean("transactionManager")
public Neo4jTransactionManager neo4jTransactionManager() {
return new Neo4jTransactionManager(sessionFactory);
}
}
注意:这有一个问题 经过测试,它这个配置支持neo4j 和 mysql,不过在项目中确实遇到了,事务的问题,发生场景是: 在spring的调度框架schedule中,出现数据库数据不能持久化到数据库,MongoDB的可以,但是mysql的就失效了,这也是某天突然发现的问题,测试了好多次才确认的。
具体原因是neo4j使用的事务管理器和spring默认的事务管理器是的,都是继承于AbstractPlatformTransactionManager
,所以才会出现上面代码中的bean名称为:transactionManager,而且这个名称也是默认的事务管理器名称;
那么spring针对这种多事务管理器也提供了ChainedTransactionManager
,它支持多个事务管理器,并且,在这种模式下,需要指定默认的事务管理器,这里我们就默认mysql的:(下面这个是对的,将两个事务管理进行合并)
@Configuration
@EnableNeo4jRepositories("com.lry.jps.repository.neo4j")
public class Neo4jConfig {
public static final String MULTI_TRANSACTION_MANAGER = "multiTansactionManager";
@Autowired
private SessionFactory sessionFactory;
@Bean("transactionManager")
@Primary
public JpaTransactionManager jpaTransactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
@Bean("neo4jTransactionManager")
public Neo4jTransactionManager neo4jTransactionManager() {
return new Neo4jTransactionManager(sessionFactory);
}
@Bean(MULTI_TRANSACTION_MANAGER)
public PlatformTransactionManager platformTransactionManager(EntityManagerFactory emf) {
return new ChainedTransactionManager(jpaTransactionManager(emf), neo4jTransactionManager());
}
}
如上配置好后,使用方式还是和之前一样,但是有使用neo4j的,需要加上事务管理的名称:@Transactional**(value = Neo4jConfig.MULTI_TRANSACTION_MANAGER)**
在进行更新操作使用spring 的jpa方式,但查询,如复杂查询,需要手动编写cql。
() 括住的是节点,{} 括住的是属性 : 开头的是标签 []括住的是关系
create(:enter{name:"6"});
# 查询出节点name为3和4的,别名a和b,建立a到b的关系;
match(a:enter{name:"3"}),(b:tt{name:"1"}) create (a)-[c:test]->(b) return a,b,c;
match(a) where a.name = '' delete a
查询标签对应的节点关系图:
match(a:enter) return a;
查询指定标签的节点关系:
match(a:enter)-[]->(b:enter) return a,b;
match(a:enter)-[:test]->(b:enter) return a,b;
match(a:tt)-[]->(b:enter) return a,b;
# 还有这种赋值返回的
match p=(a:enter)-[:test]->(b:enter) return p;
复杂查询:
# 这里通过标签查的话,会把复合的标签的阶段的都查出来,所以,增加增加查询条件name
match p=(a:enter{name:"1"})-[*1..2]->(b:enter) return p;
# 最短路劲 看下面的,这个语句有问题
# match p=shortestpath((a:enter{name:"1"})-[*1..2]->(b:enter)) return p;
# 查询两个节点间的最短,不能同一种标签的查询
# 所有路径使用*号
match (a:enter{name:"1"}),(b:enter{name:"3"}),path=shortestpath((a)-[*]->(b)) return a,b,path;
# 最长路径
# length 是计算 路径长度,所以我们按照这个长度进行排序,去第一个就是最长路径,那么相反就是最短路径
match p=((a:test)-[*1..]->(b:test)) return p order by length(p) desc limit 1
# 最短路径
# 需要排除开始节点 等于 结束节点
match p=((a:test)-[*1..]->(b:test)) where id(a)<>id(b) return p order by length(p) asc limit 1
# 多标签查询
# 标签查询也和条件查询一样,可以用and、or
match (a)
WHERE n:GraphNode OR n:Abstract
return a
# 模糊查询
match(emp) where emp.name =~'.*haha.*' return emp
# where条件句
# 和上面在的条件查询一样,不过where写法更顺手
match p=((n)-[*]->(b)) where n.mappingTaskId in ["72dd81ad-4fac-42e8-aa23-c8ebd2e149ae","sss"] return p;
match p=((n)-[*]->(b)) where n.mappingTaskId = ("72dd81ad-4fac-42e8-aa23-c8ebd2e149ae") return p;
# 查询没有关系的节点
match (a:GraphNode) where not((a)-[]->()) return a
# 查询有关系的和没有关系的节点,和计数
# 通过union 将插件结果合并
match(a)-[c]->(b) return a,count(c) as ct order by ct desc union match (a) where not((a)-[]->()) return a,0 as ct
测试例子:
List<Record> list = neo4jSession.run("match p=(a:enter{name:\"3\"})-[*1]->(b:tt) return p;").list();
Map<String,List<Object>> resultObj = new HashMap<>();
for (Record record : list){
List<String> keys = record.keys();
for (int i=0;i<keys.size();i++) {
Value value = record.get(keys.get(i));
if(resultObj.containsKey(keys.get(i))){
resultObj.get(keys.get(i)).add(value.asObject());
}else {
List<Object> s = new ArrayList<>();
s.add(value.asObject());
resultObj.put(keys.get(i),s);
}
}
}
开发注意点: