neo4j development record

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

  1. 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:

  1. 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

Added by nickminute on Wed, 08 Dec 2021 04:57:57 +0200