赞
踩
一旦我们安装Neo4j,我们可以访问Neo4j数据浏览器使用以下URL
http://localhost:7474/browser/
Neo4j数据浏览器用于执行CQL命令并查看输出输出。
这里我们需要在美元提示符处执行所有CQL命令:“$” 如
CREATE(cc:CreditCard)
在美元符号后键入命令,然后单击“执行”按钮运行命令。
查看图表形式的数据:
单击“导出CSV”按钮以csv文件格式导出结果
CQL代表Cypher查询语言。 像关系型数据库具有查询语言SQL,Neo4j使用CQL作为查询语言。
Neo4j CQL
常用的Neo4j CQL命令/条款如下:
完成上面的语法 我们基于庆余年电视剧人物关系图片:
CREATE (
<node-name>:<label-name>
[{
<property1-name>:<property1-Value>
. .......
<propertyn-name>:<propertyn-Value>
}]
)
语法说明:
语法元素 | 描述 |
---|---|
< node-name> | 它是我们将要创建的节点名称。 |
< label-name> | 它是一个节点标签名称 |
< property1-name>…< propertynname> | 属性是键值对。 定义将分配给创建节点的属性的名 称 |
< property1-value>…< propertynvalue> | 属性是键值对。 定义将分配给创建节点的属性的值 |
举例:
CREATE (person:Person)
CREATE (person:Person {cid:1,name:"范闲",age:24,gender:0,character:"A",money:1000});
CREATE (person:Person {cid:2,name:"林婉儿",age:20,gender:1,character:"B",money:800});
CREATE (person:Person {cid:3,name:"庆帝",age:49,gender:0,character:"A",money:8900});
MATCH
(
<node-name>:<label-name>
)
RETURN
<node-name>.<property1-name>,
...
<node-name>.<propertyn-name>
语法元素 | 描述 |
---|---|
< node-name> | 它是我们将要创建的节点名称。 |
< label-name> | 它是一个节点标签名称 |
< property1-name>…< propertyn-name> | 属性是键值对。 定义将分配给创建节点的属性的名称 |
举例:
MATCH (person:Person) return person
MATCH (person:Person) return person.name,person.age
match(person:Person {name:"范闲"}) return person
MATCH (<node1-name>:<node1-label-name>),(<node2-name>:<node2-label-name>) CREATE
(<node1-name>)-[<relationship-name>:<relationship-label-name>]->(<node2-name>)
RETURN 相应的内容
语法说明:
创建关系
match(person:Person {name:"范闲"}) ,(person2:Person {name:"林婉儿"})
create(person)-[r:Couple]->(person2);
查询关系
match p = (person:Person {name:"范闲"})-[r:Couple]->(person2:Person) return p
match (p1:Person {name:"范闲"})-[r:Couple]-(p2:Person) return p1,p2
match (p1:Person {name:"范闲"})-[r:Couple]-(p2:Person) return r
MATCH (<node1-label-name>:<node1-name>),(<node2-label-name>:<node2-name>) CREATE
(<node1-label-name>)-[<relationship-label-name>:<relationship-name>
{<define-properties-list>}]->(<node2-label-name>) RETURN <relationship-label-name>
其中<define-properties-list> 是分配给新创建关系的属性(名称 - 值对)的列表。
{
<property1-name>:<property1-value>,
<property2-name>:<property2-value>,
...
<propertyn-name>:<propertyn-value>
}
match(person:Person {name:"范闲"}),(person2:Person {name:"林婉儿"})
create(person)-[r:Couple{mary_date:"12/12/2014",price:55000}]->(person2) return r;
CREATE
(<node1-label-name>:<node1-name>)
-[<relationship-label-name>:<relationship-name>]->
(<node1-label-name>:<node1-name>)
create(person1:Person {cid:4,name:"长公主",age:49,gender:1,character:"A",money:5000}) -[r:Friend]->
(person2:Person {cid:7,name:"九品射手燕小乙",age:48,gender:0,character:"B",money:1000})
CREATE
(<node1-label-name>:<node1-name>{<define-properties-list>})
-[<relationship-label-name>:<relationship-name>{<define-properties-list>}]
->(<node1-label-name>:<node1-name>{<define-properties-list>})
create (person1:Person {cid:9,name:"靖王世子",age:23,gender:0,character:"A",money:3000})
<-[r:Friend {date:"11-02-2000"}]->
(person2:Person {cid:8,name:"二皇子",age:24,gender:0,character:"B",money:6000})
关系和节点的属性可以使用的类型
CREATE (<node-name>:<label-name1>:<label-name2>. ....:<label-namen>)
如:
CREATE (person:Person:Beauty:Picture {cid:20,name:"小美女"})
简单的WHERE子句
WHERE <condition>
复杂的WHERE子句
WHERE <condition> <boolean-operator> <condition>
where 中的比较运算符 和 之前mysql的相同 如 = != <> > < 等
MATCH (person:Person)
WHERE person.name = '范闲' OR person.name = '靖王世子' RETURN person
match(p:Person) where p.money>1000 return p
删除节点
match(person:Person {name:"小美女"}) delete person
删除节点及相关节点和关系。
match p = (:Person {name:"林婉儿"})-[r:Couple]-(:Person) delete r
match(:Person {name:"长公主"})-[r]-(:Person) delete r
另外:
以下命令删除所有的节点和关系
match(n) match(n)-[r]-() delete n,r
MATCH (person:Person {name:"小美女"}) REMOVE person.cid
MATCH (person:Person {cid:1}) SET person.money = 3456,person.age=25
“ORDER BY”子句,对MATCH查询返回的结果进行排序。
我们可以按升序或降序对行进行排序。
默认情况下,它按升序对行进行排序。 如果我们要按降序对它们进行排序,我们需要使用DESC子句。
MATCH (person:Person)
RETURN person.name,person.money ORDER BY person.money DESC
Neo4j CQL已提供“SKIP”子句来过滤或限制查询返回的行数。 它修整了CQL查询结果集顶部的结果。 Neo4j CQL已提供“LIMIT”子句来过滤或限制查询返回的行数。 它修剪CQL查询结果集底部的结果。
MATCH (person:Person)
RETURN ID(person),person.name,person.money ORDER BY person.money DESC skip 4 limit 2
这个函数的用法就像SQL中的distinct关键字,返回的是所有不同值。
MATCH (p:Person) RETURN Distinct(p.character)
MATCH (p:Person) RETURN ID(p),LOWER(p.character)
match(p:Person) return p.character,
lower(p.character),p.name,substring(p.name,2),replace(p.name,"子","z i")
MATCH (p:Person)
RETURN MAX(p.money),SUM(p.money)
match p = (:Person {name:"林婉儿"})-[r:Couple]-(:Person) RETURN STARTNODE(r)
MATCH p=shortestPath( (node1)-[*]-(node2) )
RETURN length(p), nodes(p)
MATCH p=shortestPath((person:Person {name:"王启年"})-[*]-(person2:Person {name:"九品射手燕小乙"}) ) RETURN length(p), nodes(p)
查询三层级关系节点如下: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
match (na:Person{name:"范闲"})-[re]->(nb:Person)-[re2]->(nc:Person) return na,re,nb,re2,nc 为了方便,可以将查询结果赋给变量,然后返回
match data=(na:Person{name:"范闲"})-[re]->(nb:Person)-[re2]->(nc:Person) return data
当实现多深度关系节点查询时,显然使用以上方式比较繁琐。
可变数量的关系->节点可以使用-[:TYPE*minHops..maxHops]-。
查询:
match data=(na:Person{name:"范闲"})-[*1..2]-(nb:Person) return data
为了保持数据的完整性和保证良好的事务行为,Neo4j也支持ACID特性 。
注意:
介绍
Neo4j CQL支持节点或关系属性上的索引,以提高应用程序的性能。
可以为具有相同标签名称的属性上创建索引。
可以在MATCH或WHERE等运算符上使用这些索引列来改进CQL 的执行。
创建单一索引
CREATE INDEX ON :Label(property) 例如:
CREATE INDEX ON :Person(name)
创建复合索引
CREATE INDEX ON :Person(age, gender)
全文模式索引
之前的常规模式索引只能对字符串进行精确匹配或者前后缀索引(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
查看和删除索引
call db.indexes 或者 :schema
DROP INDEX ON :Person(name)
DROP INDEX ON :Person(age, gender)
call db.index.fulltext.drop(“nameAndDescription”)
唯一性约束
作用:
创建唯一性约束
CREATE CONSTRAINT ON (变量:<label_name>) ASSERT 变量.<property_name> IS UNIQUE
具体实例:
CREATE CONSTRAINT ON (person:Person) ASSERT person.name IS UNIQUE
删除唯一性约束
DROP CONSTRAINT ON (cc:Person) ASSERT cc.name IS UNIQUE
属性存在约束 (企业版中可用)
CREATE CONSTRAINT ON (p:Person) ASSERT exists(p.name)
查看约束
call db.constraints :schema
在对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
* soft nofile 65535
* hard nofile 65535
# 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
MATCH (n)
OPTIONAL MATCH (n)-[r]->() RETURN count(n.name) + count(r);
Cypher查询计划程序将每个查询转换为执行计划。 执行计划告诉Neo4j在执行查询时要执行哪些操 作。
对执行计划的生成,Neo4j使用的都是基于成本的优化器(Cost Based Optimizer,CBO),用于制订 精确的执行过程。可以采用如下两种不同的方式了解其内部的工作机制:
EXPLAIN:是解释机制,加入该关键字的Cypher语句可以预览执行的过程但并不实际执行,所以也不 会产生任何结果。
PROFILE:则是画像机制,查询中使用该关键字,不仅能够看到执行计划的详细内容,也可以看到查询 的执行结果。
关注指标:
estimated rows: 需要被扫描行数的预估值
dbhits: 实际运行结果的命中绩效
两个值都是越小越好
使用索引和不使用索引对比
MATCH (p { name : ‘范闲’ }) RETURN p
在之前加上profile来进行查询,可以查看查询计划
嵌入式Neo4j数据库是性能的最佳选择。 通过指定数据存储的路径以编程方式访问嵌入式数据库。
我们选择嵌入式数据库出于以下原因:
Neo4j Server是相互操作性,安全性和监控的最佳选择。 实际上,REST接口允许所有现代平台和编程 语言与它进行互操作。 此外,作为独立应用程序,它比嵌入式配置更安全(客户端中的潜在故障不会影 响服务器),并且更易于监控。 如果我们选择使用这种模式,我们的应用程序将充当Neo4j服务器的客 户端。要连接到Neo4j服务器,可以使用任何编程语言的REST 访问数据库。
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.5.5</version>
</dependency>
package com.lagou; 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.lagou; 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(); } }
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>3.2.10</version>
</dependency>
package com.lagou; 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.lagou; 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(); } }
<?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.lagou</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>
package com.lagou.bean; import org.neo4j.ogm.annotation.GeneratedValue; import org.neo4j.ogm.annotation.Id; import org.neo4j.ogm.annotation.NodeEntity; import org.neo4j.ogm.annotation.Property; @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; ………… ………… ………… get set toString
package com.lagou.repository;
import com.lagou.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);
}
或者使用
@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);
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
package com.lagou.service; import com.lagou.bean.Person; import com.lagou.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); }
package com.lagou; import com.lagou.bean.Person; import com.lagou.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("王启年", "九品射手燕小 乙")); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。