Article catalog
docker setup
Pull image
docker pull neo4j
start-up
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
If no password is set, the default password is neo4j/neo4j If verification is not required, configure --env NEO4J_AUTH=none
Start with docker compose
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
DockerFile repackaging
I think it's troublesome to configure it after startup. Repackage it
Springboot usage
- pom
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-neo4j</artifactId> </dependency>
First of all, neo4j's transactions are different from those of mysql and need to be configured manually: For example, the following (just for example, is the following example right or wrong to some extent)
@Configuration @EnableNeo4jRepositories("com.lry.jps.repository.neo4j") public class Neo4jConfig { @Autowired private SessionFactory sessionFactory; @Bean("transactionManager") public Neo4jTransactionManager neo4jTransactionManager() { return new Neo4jTransactionManager(sessionFactory); } }
Note: there is a problem After testing, the configuration supports neo4j and mysql. However, transaction problems are encountered in the project. The scenarios are: In the scheduling framework schedule of spring, the database data cannot be persisted to the database. MongoDB can, but mysql fails. This is also a problem suddenly found one day. It was confirmed after many tests.
The specific reason is that neo4j uses the same transaction manager as spring's default transaction manager, which inherits from AbstractPlatformTransactionManager, so the bean name in the above code is: transactionManager, and this name is also the default transaction manager name; spring also provides ChainedTransactionManager for this kind of multi transaction manager, which supports multiple transaction managers. In this mode, you need to specify the default transaction manager. Here, we will default mysql: (the following is right. Merge the two transaction managers)
@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()); } }
After the above configuration, the usage is the same as before, but if neo4j is used, the name of transaction management needs to be added: @ Transactional**(value = Neo4jConfig.MULTI_TRANSACTION_MANAGER)**
spring's jpa method is used for updating, but queries, such as complex queries, need to be written manually in cql.
neo4j syntax
() encloses nodes and {} encloses attributes: the label [] at the beginning encloses relationships
Create node
create(:enter{name:"6"});
Create relationship
# Query the aliases A and b of nodes with name s 3 and 4, and establish the relationship between a and b; match(a:enter{name:"3"}),(b:tt{name:"1"}) create (a)-[c:test]->(b) return a,b,c;
delete
match(a) where a.name = '' delete a
query
Query the node diagram corresponding to the tag:
match(a:enter) return a;
Query the node relationship of the specified label:
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; # And this assignment returns match p=(a:enter)-[:test]->(b:enter) return p;
Complex query:
# If you check the tags here, you will find all the phases of the composite tags. Therefore, add the query condition name match p=(a:enter{name:"1"})-[*1..2]->(b:enter) return p; # The shortest way is to look at the following sentence. There is a problem with this sentence # match p=shortestpath((a:enter{name:"1"})-[*1..2]->(b:enter)) return p; # Query the shortest time between two nodes. You cannot query the same label # All paths use the * sign match (a:enter{name:"1"}),(b:enter{name:"3"}),path=shortestpath((a)-[*]->(b)) return a,b,path; # Longest path # Length is the calculated path length, so we sort according to this length. The first is the longest path, and the opposite is the shortest path match p=((a:test)-[*1..]->(b:test)) return p order by length(p) desc limit 1 # Shortest path # You need to exclude the start node equal to the end node match p=((a:test)-[*1..]->(b:test)) where id(a)<>id(b) return p order by length(p) asc limit 1 # Multi label query # Label query is also the same as condition query. You can use and or match (a) WHERE n:GraphNode OR n:Abstract return a # Fuzzy query match(emp) where emp.name =~'.*haha.*' return emp # where conditional sentence # It is the same as the condition query above, but where is easier to write 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; # Query unrelated nodes match (a:GraphNode) where not((a)-[]->()) return a # Query related and unrelated nodes, and count # Merge plug-in results through 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
Test example:
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); } } }
Development considerations:
- The results obtained by using cql query are the same as those returned by return in the statement. For example, match (a) - [C] - > (b) return a, B, C. in the results, the results are returned in this order. If match P = ((a) - [C] - > (b)) return p; Then p contains a b c