CQL函數
1. 字符串函數
功能 | 描述 |
---|---|
UPPER | 將所有字母改爲大寫 |
LOWER | 將所有字母改爲小寫 |
SUBSTRING | 將獲取指定範圍的子字符串 |
REPLACE | 替換一個字符串的子字符串 |
match (p:Person) return ID(p),LOWER(p.character)
2. 聚合函數
聚集功能 | 描述 |
---|---|
COUNT | 它返回由MATCH命令返回的行數 |
MAX | 它從MATCH命令返回的一組行返回最大值 |
MIN | 它返回由MATCH命令返回的一組行的最小值 |
SUM | 它返回由MATCH命令返回的所有行的求和 |
AVG | 它返回由MATCH命令返回的所有行的平均值 |
示例:
match (p:Person) return max(p.money)
3. 關係函數
功能 | 描述 |
---|---|
STARTNODE | 用於知道關係的開始節點 |
ENDNODE | 用於知道關係的結束節點 |
ID | 用於知道關係的ID |
TYPE | 用於知道字符串表示中的一個關係的TYPE |
示例:
match p=(:Person {name:"範閒"})-[r:Couple]-(:Person) return ENDNODE(r)
match p=(:Person {name:"範閒"})-[r:Couple]-(:Person) return type(r)
4. 返回最短路徑
shortestPath函數
示例:
match p=shortestPath((person:Person {cid:1})-[*]-(person2:Person {cid:8})) return length(p),nodes(p)
CQL多深度關係節點
1. 使用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
2. 直接拼接關係節點查詢
match data=(na:Person{name:"範閒"})-[re]->(nb:Person)-[re2]->(nc:Person) return data
3. 使用深度運算符
-[:TYPE*minHops..maxHops]-
minHops代表最小深度,maxHops代表最大深度。
match data=(na:Person{cid:1})-[*1..2]-(:Person) return data
事務
Neo4j支持ACID特性
- 所有對Neo4j數據庫的數據修改操作都必須封裝在事務中
- 默認的isolation level是READ_COMMITTED
- 死鎖保護已經內置到核心事務管理。
- 除特殊說明,Neo4j的API操作都是線程安全的,Neo4j數據庫的操作也就沒有必要使用外部的同步方法。
索引
Neo4j支持在節點或關係的屬性上建立索引,以提高應用程序的性能。可以在Match或where等運算符上使用這些索引改進SQL的執行。
- 單一索引
CREATE INDEX ON :Label(property)
示例:
create index on:Person(name)
- 複合索引
create index on:Person(age,gender)
- 全文索引
常規索引只能對字符串進行精確匹配或前後綴索引,而全文索引可以匹配字符串任何位置的詞語。
使用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")
約束
作用:唯一性約束用於避免重複記錄
1. 創建唯一性約束
CREATE CONSTRAINT ON (變量:<label_name>) ASSERT 變量.<property_name> IS UNIQUE
示例:
create constraint on(person:Person) assert person.name is unique
2. 刪除唯一性約束
drop constraint on (person:Person) assert person.name is unique
3. 查看約束
call db.constraints
#或
:schema
Neo4j服務管理
1. 備份和恢復
- 備份之前先停止服務
bin/neo4j stop
- 備份命令
bin/neo4j-admin dump --database=graph.db --to=/usr/local/qyn.dump
然後啓動服務,刪除所有數據。然後在停止服務,準備恢復
match (p)-[r]-() delete p,r
- 恢復命令
bin/neo4j-admin load --from=/usr/local/qyn.dump --database=graph.db --force
注意:運行數據備份可能會警告
WARNING: Max 1024 open files allowed, minimum of 40000 recommended. See the Neo4j manual
編輯這個文件:vim /etc/security/limits.conf,在文件最後面加上這段,修改最大打開文件限制,在重啓服務器就行了。
* soft nofile 65535
* hard nofile 65535
2. Neo4j調優
2.1 調整neo4j配置文件
# neo4j初始堆內存
dbms.memory.heap.initial_size=512m
# 最大堆內存
dbms.memory.heap.max_size=512m
# pagecache大小,官方建議設爲:(總內存-dbms.memory.heap.max_size)/2
dbms.memory.pagecache.size=10g
2.2 數據預熱
match (n)
optional match (n)-[r]->()
return count(n.name)+count(r)
- 使用執行計劃命令優化
有如下兩個命令:
- Explain :解釋機制,加入該關鍵字的Cypher語句可以預覽執行的過程但是不實際執行
- Profile:畫像機制,查詢中使用該關鍵字能夠看到執行計劃詳細內容,還能看到查詢的結果
示例:
profile match (p:Person {name:"範閒"}) return p
需要關注指標:
關注指標:
estimated rows: 需要被掃描行數的預估值
dbhits: 實際運行結果的命中績效
Neo4j 程序訪問
1. 數據庫訪問方式
Neo4j訪問有兩種方式:
- 嵌入式數據庫
- 服務器模式(通過REST的訪問)
嵌入式數據庫
嵌入式Neo4j數據庫是性能的最佳選擇,通過指定數據存儲的路徑以編程的方式訪問。我們選擇嵌入式數據庫有如下的原因:
- 使用java作爲編程語言
- 應用程序獨立
- 程序追求很高的性能
服務器模式
Neo4j Server是相互操作性、安全性和監控的最佳選擇。實際上,REST接口允許所有現代平臺和編程語言與它進行交互操作。此外,作爲獨立應用程序,他比嵌入式配置更安全(客戶端的故障不會影響服務器),更易於監控。而且可以使用任意編程語言以REST的方式訪問數據庫。
2. Java客戶端訪問
2.1 嵌入式模式
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.5.5</version>
</dependency>
新增數據
public static void add(){
GraphDatabaseService graphDb= new GraphDatabaseFactory().newEmbeddedDatabase(databaseDirectory);
System.out.println("database load");
Transaction tx = graphDb.beginTx();
Node node = graphDb.createNode();
node.setProperty("name","張三");
node.setProperty("character","A");
node.setProperty("money",2330);
node.addLabel(() -> "Person");
tx.success();
tx.close();
graphDb.shutdown();
}
查詢數據
public static void query(){
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<>();
paramerters.put("money",2500);
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.getProperties("name"),nd.getProperties("money"));
}
}
tx.success();
tx.close();
graphDb.shutdown();
}
2.2 服務器模式
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>3.2.10</version>
</dependency>
查詢示例:
public static void query(){
Driver driver = GraphDatabase.driver("bolt://192.168.56.115: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, Values.parameters("money", 400));
while (result.hasNext()){
Record record = result.next();
System.out.println(record.get("name").asString()+" "+record.get("money").asDouble());
}
session.close();
driver.close();
}
SpringBoot 整合Neo4j
- 引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
- 編寫配置文件
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=123456
spring.data.neo4j.uri= bolt://192.168.56.115:7687
- 建立實體類
@NodeEntity
@Data
public class Person {
@Id
@GeneratedValue
private Long id;
private Integer cid;
private String name;
private String character;
private Double money;
private Integer gender;
private Integer age;
private String description;
@Relationship(type = "Friend",direction = Relationship.OUTGOING)
private Set<Person> relationPersons;
- 編寫數據持久層
@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..2] - (person2:Person {name:{1}})) return p ")
List<Person> shortestPath(String startName,String endName);
}
- 測試
Iterable<Person> all = personRepository.findAll();
System.out.println(all);