当前位置:   article > 正文

Neo4j 基础简介二_neo4j shortestpath

neo4j shortestpath

Neo4j CQL高级

CQL 函数

字符串函数
S.No.功能描述
1UPPER它用于将所有字母更改为大写字母。
2LOWER它用于将所有字母改为小写字母。
3SUBSTRING它用于获取给定String的子字符串。
4REPLACE它用于替换一个字符串的子字符串。
MATCH (p:Person) 
RETURN ID(p),LOWER(p.character)
  • 1
  • 2
match(p:Person) 
return p.character,lower(p.character),
p.name,substring(p.name,2),replace(p.name,"子","z i")
  • 1
  • 2
  • 3
聚合函数
S.No.聚集功能描述
1COUNT它返回由MATCH命令返回的行数。
2MAX它从MATCH命令返回的一组行返回最大值。
3MIN它返回由MATCH命令返回的一组行的最小值。
4SUM它返回由MATCH命令返回的所有行的求和值。
5AVG它返回由MATCH命令返回的所有行的平均值。
MATCH (p:Person) 
RETURN MAX(p.money),SUM(p.money)
  • 1
  • 2
关系函数
S.No.功能描述
1STARTNODE它用于知道关系的开始节点。
2ENDNODE它用于知道关系的结束节点。
3ID它用于知道关系的ID。
4TYPE它用于知道字符串表示中的一个关系的TYPE。
match p = (:Person {name:"林婉儿"})-[r:Couple]-(:Person) 
RETURN STARTNODE(r)
  • 1
  • 2
shortestPath 函数返回最短的path
MATCH p=shortestPath( (node1)-[*]-(node2) ) RETURN length(p), nodes(p)
  • 1
MATCH p=shortestPath((person:Person {name:"王启年"})-[*]-(person2:Person {name:"九品射手燕小乙"}) ) RETURN length(p), nodes(p)
  • 1

CQL多深度关系节点

使用with关键字

查询三层级关系节点如下:with可以将前面查询结果作为后面查询条件

match (na:Person)-[re]->(nb:Person) where na.name="范闲" WITH na,re,nb match (nb:Person)-
[re2]->(nc:Person) return na,re,nb,re2,nc

match (na:Person)-[re]->(nb:Person) where na.name="林婉儿" WITH na,re,nb match (nb:Person)-
[re2]->(nc:Person) return na,re,nb,re2,nc

match (na:Person)-[re]-(nb:Person) where na.name="林婉儿" WITH na,re,nb match (nb:Person)-
[re2]->(nc:Person) return na,re,nb,re2,nc

match (na:Person)-[re]-(nb:Person) where na.name="林婉儿" WITH na,re,nb match (nb:Person)-
[re2:Friends]->(nc:Person) return na,re,nb,re2,nc
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
直接拼接关系节点查询
match (na:Person{name:"范闲"})-[re]->(nb:Person)-[re2]->(nc:Person) return na,re,nb,re2,nc
  • 1

为了方便,可以将查询结果赋给变量,然后返回

match data=(na:Person{name:"范闲"})-[re]->(nb:Person)-[re2]->(nc:Person) return data
  • 1
使用深度运算符

当实现多深度关系节点查询时,显然使用以上方式比较繁琐。
可变数量的关系->节点可以使用-[:TYPE*minHops…maxHops]-。
查询:

match data=(na:Person{name:"范闲"})-[*1..2]-(nb:Person) return data
  • 1

事务

为了保持数据的完整性和保证良好的事务行为,Neo4j也支持ACID特性 。
注意:

  1. 所有对Neo4j数据库的数据修改操作都必须封装在事务里。
  2. 默认的isolation level是READ_COMMITTED。
  3. 死锁保护已经内置到核心事务管理 。 (Neo4j会在死锁发生之前检测死锁并抛出异常。在异常抛出之前,事务会被标志为回滚。当事务结束时,事务会释放它所持有的锁,则该事务的锁所引起的死锁也就是解 除,其他事务就可以继续执行。当用户需要时,抛出异常的事务可以尝试重新执行)
  4. 除特别说明,Neo4j的API的操作都是线程安全的,Neo4j数据库的操作也就没有必要使用外部的同步方法。

索引

简介

Neo4j CQL支持节点或关系属性上的索引,以提高应用程序的性能。
可以为具有相同标签名称的属性上创建索引。
可以在MATCH或WHERE等运算符上使用这些索引列来改进CQL 的执行。

创建单一索引
CREATE INDEX ON :Label(property)
  • 1

例如:

CREATE INDEX ON :Person(name)
  • 1
创建复合索引
CREATE INDEX ON :Person(age, gender)
  • 1
全文模式索引

之前的常规模式索引只能对字符串进行精确匹配或者前后缀索引(startswith,endswith,contains),全文索引将标记化索引字符串值,因此它可以匹配字符串中任何位置的术语。索引字符串如何被标记化并分解为术语,取决于配置全文模式索引的分析器。索引是通过属性来创建,便于快速查找节点或者关系。

创建和配置全文模式索引

使用db.index.fulltext.createNodeIndex和db.index.fulltext.createRelationshipIndex创建全文模式索引。在创建索引时,每个索引必须为每个索引指定一个唯一的名称,用于在查询或删除索引时引用相关的特定索引。然后,全文模式索引分别应用于标签列表或关系类型列表,分别用于节点和关系索引,然后应用于属性名称列表。

call db.index.fulltext.createNodeIndex("索引名",[Label,Label],[属性,属性]) 

call db.index.fulltext.createNodeIndex("nameAndDescription",["Person"],["name", "description"])

call db.index.fulltext.queryNodes("nameAndDescription", "范闲") YIELD node, score RETURN node.name, node.description, score
  • 1
  • 2
  • 3
  • 4
  • 5
查看和删除索引
call db.indexes 或者 :schema

DROP INDEX ON :Person(name)

DROP INDEX ON :Person(age, gender)

call db.index.fulltext.drop("nameAndDescription")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

约束

唯一性约束
  • 作用

    • 避免重复记录。
    • 强制执行数据完整性规则
  • 创建唯一性约束

    CREATE CONSTRAINT ON (变量:<label_name>) ASSERT 变量.<property_name> IS UNIQUE
    
    • 1
  • 具体实例:

    CREATE CONSTRAINT ON (person:Person) ASSERT person.name IS UNIQUE
    
    • 1
  • 删除唯一性约束

    DROP CONSTRAINT ON (cc:Person) ASSERT cc.name IS UNIQUE
    
    • 1
属性存在约束 (企业版中可用)
CREATE CONSTRAINT ON (p:Person) ASSERT exists(p.name)
  • 1
查看约束
call db.constraints :schema
  • 1

Neo4j之Admin管理员操作

Neo4j - 数据库备份和恢复

  • 在对Neo4j数据进行备份、还原、迁移的操作时,首先要关闭neo4j

    ./bin/neo4j stop
    
    • 1
  • 数据备份到文件

    ./bin/neo4j-admin dump --database=graph.db --to=/root/qyn.dump
    
    • 1
  • 还原、迁移之前 ,关闭neo4j服务。操作同上

    ./bin/neo4j-admin load --from=/root/qyn.dump --database=graph.db --force
    
    • 1
  • 重启服务

    ./bin/neo4j start
    
    • 1

注意,运行数据备份可能会警告

WARNING: Max 1024 open files allowed, minimum of 40000 recommended. See the Neo4j manual
  • 1
  • 编辑这个文件

    vi /etc/security/limits.conf
    
    • 1
  • 在文件最后加入下面这段 修改最大打开文件限制

    * soft nofile 65535 
    * hard nofile 65535
    
    • 1
    • 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
  2. neo4j刚启动数据是冷的需要预热

    MATCH (n) OPTIONAL MATCH (n)-[r]->() 
    RETURN count(n.name) + count(r);
    
    • 1
    • 2
  3. 查看执行计划进行索引优化
    Cypher查询计划程序将每个查询转换为执行计划。 执行计划告诉Neo4j在执行查询时要执行哪些操作。

    对执行计划的生成,Neo4j使用的都是基于成本的优化器(Cost Based Optimizer,CBO),用于制订精确的执行过程。可以采用如下两种不同的方式了解其内部的工作机制:

    • EXPLAIN:是解释机制,加入该关键字的Cypher语句可以预览执行的过程但并不实际执行,所以也不会产生任何结果。

    • PROFILE:则是画像机制,查询中使用该关键字,不仅能够看到执行计划的详细内容,也可以看到查询的执行结果。

    关注指标: 
    	estimated rows: 需要被扫描行数的预估值 
    	dbhits: 实际运行结果的命中绩效 
    	两个值都是越小越好
    
    • 1
    • 2
    • 3
    • 4

    使用索引和不使用索引对比
    MATCH (p { name : ‘范闲’ }) RETURN p
    在之前加上profile来进行查询,可以查看查询计划

Neo4j 程序访问

Neo4j数据库访问

Neo4j访问的两种方式
  • 嵌入式数据库
  • 服务器模式(通过REST的访问)

它是由应用程序的性质(neo4j是独立服务器 还是和程序在一起),性能,监控和数据安全性来决定架构选择。

An embedded database(嵌入式数据库)

嵌入式Neo4j数据库是性能的最佳选择。 通过指定数据存储的路径以编程方式访问嵌入式数据库。

我们选择嵌入式数据库出于以下原因:

  • 使用Java作为我们项目的编程语言时
  • 应用程序是独立的
  • 程序追求很高的性能
Neo4j Server(服务器模式)

Neo4j Server是相互操作性,安全性和监控的最佳选择。 实际上,REST接口允许所有现代平台和编程语言与它进行互操作。 此外,作为独立应用程序,它比嵌入式配置更安全(客户端中的潜在故障不会影响服务器),并且更易于监控。 如果我们选择使用这种模式,我们的应用程序将充当Neo4j服务器的客户端。要连接到Neo4j服务器,可以使用任何编程语言的REST 访问数据库。

Java客户端操作Neo4j

嵌入式模式

引入依赖

<dependency> 
	<groupId>org.neo4j</groupId> 
	<artifactId>neo4j</artifactId> 
	<version>3.5.5</version> 
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

新增 Java代码

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(); 
	} 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

查询所有Java代码

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(); 
	} 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
服务器模式

依赖

<dependency> 
	<groupId>org.neo4j</groupId> 
	<artifactId>neo4j-ogm-bolt-driver</artifactId> 
	<version>3.2.10</version> 
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

代码

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(); 
	} 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
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(); 
	} 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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.learn</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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
  2. 建立实体类(get、set和ToString方法省略)

    @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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  3. 数据持久化类

    @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); 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    或者使用

    @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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  5. 编写服务类

    @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); 
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  6. 编写测试类

    @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("王启年", "九品射手燕小 乙"));
    	} 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/1013638
推荐阅读
相关标签
  

闽ICP备14008679号