目录
5.1.2 An embedded database(嵌入式数据库)
第四部分 Neo4j之Admin管理员操作
4.1 Neo4j - 数据库备份和恢复
在对Neo4j数据进行备份、还原、迁移的操作时,首先要关闭neo4j
./bin/neo4j stop
数据备份到文件
./bin/neo4j-admin dump --database=graph.db --to=/root/qyn.dump
还原、迁移之前 ,关闭neo4j服务。操作同上
./bin/neo4j-admin load --from=/root/qyn.dump --database=graph.db --force
重启服务
./bin/neo4j start
注意,运行数据备份可能会警告
WARNING: Max 1024 open files allowed, minimum of 40000 recommended. See the Neo4j manual
1.编辑这个文件
vi /etc/security/limits.conf
在文件最后加入下面这段 修改最大打开文件限制
* soft nofile 65535
* hard nofile 65535
2.重启服务器
再次执行上面的步骤 警告就没有了
4.2 调优思路
1.增加服务器内存 和 调整neo4j配置文件
# java heap 初始值
dbms.memory.heap.initial_size=1g
# java heap 最大值,一般不要超过可用物理内存的80% dbms.memory.heap.max_size=16g
# pagecache大小,官方建议设为:(总内存-dbms.memory.heap.max_size)/2, dbms.memory.pagecache.size=2g
2.neo4j刚启动数据是冷的需要预热
MATCH (n)
OPTIONAL MATCH (n)-[r]->()
RETURN count(n.name) + count(r);
3. 查看执行计划进行索引优化
Cypher查询计划程序将每个查询转换为执行计划。 执行计划告诉Neo4j在执行查询时要执行哪些操 作。
对执行计划的生成,Neo4j使用的都是基于成本的优化器(Cost Based Optimizer,CBO),用于制订 精确的执行过程。可以采用如下两种不同的方式了解其内部的工作机制:
EXPLAIN:是解释机制,加入该关键字的Cypher语句可以预览执行的过程但并不实际执行,所以也不 会产生任何结果。
PROFILE:则是画像机制,查询中使用该关键字,不仅能够看到执行计划的详细内容,也可以看到查询 的执行结果。
关注指标:
estimatedrows: 需要被扫描行数的预估值
dbhits: 实际运行结果的命中绩效
两个值都是越小越好
使用索引和不使用索引对比
MATCH (p { name : '范闲' }) RETURN p
在之前加上profile来进行查询,可以查看查询计划
第五部分 Neo4j 程序访问
5.1 Neo4j数据库访问
5.1.1 Neo4j访问的两种方式
- 嵌入式数据库
- 服务器模式(通过REST的访问)
它是由应用程序的性质(neo4j是独立服务器 还是和程序在一起),性能,监控和数据安全性来决定架构选择。
5.1.2 An embedded database(嵌入式数据库)
嵌入式Neo4j数据库是性能的最佳选择。 通过指定数据存储的路径以编程方式访问嵌入式数据库。
我们选择嵌入式数据库出于以下原因:
- 使用Java作为我们项目的编程语言时
- 应用程序是独立的
- 程序追求很高的性能
5.1.3 Neo4j Server(服务器模式)
Neo4j Server是相互操作性,安全性和监控的最佳选择。 实际上,REST接口允许所有现代平台和编程 语言与它进行互操作。 此外,作为独立应用程序,它比嵌入式配置更安全(客户端中的潜在故障不会影 响服务器),并且更易于监控。 如果我们选择使用这种模式,我们的应用程序将充当Neo4j服务器的客 户端。要连接到Neo4j服务器,可以使用任何编程语言的REST 访问数据库。
5.2 Java客户端操作Neo4j
1.嵌入式模式
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.5.5</version>
</dependency>
package com.ch;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class EmbeddedNeo4jAdd {
private static final File databaseDirectory = new File("target/graph.db");
public static void main(String[] args) {
GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(databaseDirectory);
System.out.println("Database Load!");
Transaction tx = graphDb.beginTx();
Node n1 = graphDb.createNode();
n1.setProperty("name", "张三");
n1.setProperty("character", "A");
n1.setProperty("gender", 1);
n1.setProperty("money", 1101);
n1.addLabel(new Label() {
@Override
public String name() {
return "Person";
}
});
String cql = "CREATE (p:Person{name:'李 四',character:'B',gender:1,money:21000})";
graphDb.execute(cql);
tx.success();
tx.close();
System.out.println("Database Shutdown!"); graphDb.shutdown();
}
}
package com.ch;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class EmbeddedNeo4jQueryAll {
private static final File databaseDirectory = new File("target/graph.db");
public static void main(String[] args) {
GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(databaseDirectory);
System.out.println("Database Load!");
String cql = "MATCH (a:Person) where a.money < $money return a";
Map<String, Object> paramerters = new HashMap<String, Object>();
paramerters.put("money", 25000);
Transaction tx = graphDb.beginTx();
Result result = graphDb.execute(cql, paramerters);
while (result.hasNext()) {
Map<String, Object> row = result.next();
for (String key : result.columns()) {
Node nd = (Node) row.get(key);
System.out.printf("%s = %s:%s%n", key,
nd.getProperty("name"), nd.getProperty("money"));
}
}
tx.success();
tx.close();
System.out.println("Database Shutdown!");
graphDb.shutdown();
}
}
2.服务器模式
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>3.2.10</version>
</dependency>
package com.ch;
import org.neo4j.driver.*;
import static org.neo4j.driver.Values.parameters;
public class Neo4jServerMain {
public static void main(String[] args) {
Driver driver = GraphDatabase.driver("bolt://127.0.0.1:7687", AuthTokens.basic("neo4j", "123456"));
Session session = driver.session();
String cql = "MATCH (a:Person) WHERE a.money > $money " +
"RETURN a.name AS name, a.money AS money order by a.money ";
Result result = session.run(cql, parameters("money", 1000));
while (result.hasNext()) {
Record record = result.next();
System.out.println(record.get("name").asString() + " " +
record.get("money").asDouble());
}
session.close();
driver.close();
}
}
package com.ch;
import org.neo4j.driver.*;
import static org.neo4j.driver.Values.parameters;
public class Neo4jServerMain2 {
public static void main(String[] args) {
Driver driver = GraphDatabase.driver("bolt://127.0.0.1:7687", AuthTokens.basic("neo4j", "123456"));
Session session = driver.session();
String cql = "MATCH p=shortestPath((person:Person {name:$startName})- [*]-(person2:Person { name: $endName } ))RETURN p";
Result result = session.run(cql, parameters("startName", "王启年", " endName", " 九品射手燕小乙"));
while (result.hasNext()) {
Record record = result.next();
System.out.println(record);
}
session.close();
driver.close();
}
}
5.3 SpringBoot 整合Neo4j
1.导入jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ch</groupId>
<artifactId>neo4j_springboot_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.11</java.version>
</properties>
<dependencies>
<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>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.建立实体类
package com.ch.bean;
import lombok.Data;
import org.neo4j.ogm.annotation.*;
import java.util.Set;
@Data
@NodeEntity
public class Person {
@Id
@GeneratedValue
private Long id;
@Property("cid")
private int pid;
@Property
private String name;
private String character;
private double money;
private int gender;
private int age;
private String description;
@Relationship(type = "Friends", direction = Relationship.INCOMING)
private Set<Person> relationPersons;
}
3.数据持久化类
package com.ch.repository;
import com.ch.bean.Person;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository
public interface PersonRepository extends Neo4jRepository<Person, Long> {
@Query("match(p:Person) where p.money > {0} return p")
List<Person> personList(double money);
@Query("MATCH p=shortestPath( " +
"(person:Person {name:{0}}) " +
"-[*1..4]- " +
"(person2:Person{name:{1}}) ) " +
"RETURN p")
List<Person> shortestPath(String startName, String endName);
}
或者使用
package com.ch.repository;
import com.ch.bean.Person;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository
public interface PersonRepository extends Neo4jRepository<Person, Long> {
@Query("match(p:Person) where p.money>{money} return p")
List<Person> personList(@Param("money") double money);
/**
* 指定开始的名字 和 结束的名字 查询最短路径 限定深度为4以层包含4
*/
@Query("match p=shortestPath(" +
"(person:Person{name:{startName}})" +
"-[*1..4] - " +
"(person2:Person{name:{endName}})) " +
"return p")
List<Person> shortestPath(@Param("startName") String startName,
@Param("endName") String endName);
}
4. 配置文件 application.yml
spring:
data:
neo4j:
username:neo4j
password:123456
uri:bolt://192.168.211.133:7687
// #uri: http://192.168.211.133:7474
// #uri: file:///target/graph.db
5.编写服务类
package com.ch.service;
import com.ch.bean.Person;
import com.ch.repository.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class Neo4jPersonService {
@Autowired
private PersonRepository personRepository;
public List<Person> personList() {
return personRepository.personList();
}
public Person save(Person person) {
return personRepository.save(person);
}
public List<Person> shortestPath(String startName, String endName) {
return personRepository.shortestPath(startName, endName);
}
}
6.编写测试类
package com.ch;
import com.ch.bean.Person;
import com.ch.service.Neo4jPersonService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import java.util.List;
@SpringBootApplication
public class TestNeo4jBootApp {
public static void main(String[] args) {
ApplicationContext app = SpringApplication.run(TestNeo4jBootApp.class, args);
Neo4jPersonService personService = app.getBean(Neo4jPersonService.class);
System.out.println(personService);
List<Person> datas = personService.personListAll();
System.out.println(datas);
System.out.println(personService.shortestPath("王启年", "九品射手燕小乙"));
}
}