3 个不稳定版本
0.2.2 | 2024年3月17日 |
---|---|
0.2.1 | 2022年8月26日 |
0.1.4 | 2022年8月25日 |
#253 在 数据库接口
58KB
1K SLoC
Neo4j 查询构建器
Neo4j 和 Cypher 的灵活直观查询构建器。用 Rust 编写查询就像在 Cypher 中编写一样。
安装
neo4j_cypher = { version = "0.2", features=["derive"] }
使用方法
容器属性
-
#[cypher(rename = "...")]
当您想在代码中使用名称 A,但在 Neo4j 中希望将其保存为名为 B 的节点结构时,可以使用此属性。
字段属性
-
#[cypher(rename = "...")]
重命名属性也可以用作字段属性。其工作原理与上述描述类似。应在您想自动更改使用 Neo4j 实体属性对象构建查询时字段名称时使用。
-
#[cypher(skip)]
当您想隐藏在构建查询时的一些结构字段时,请使用此属性。
-
#[cypher(label)]
如果您想将字段值用作节点的标签,则可以使用此类属性。建议使用枚举作为此类字段的值。
-
#[cypher(default)]
如果字段类型是某种类型的
Option<T>
,您可以使用此属性,并且当字段值为None
时,将为该类型设置默认值。注意:对于使用简单属性 default 的类型,必须实现 trait
Default
的强制实现。 -
#[cypher(default = "...")]
如果为整个类型设置默认值不适用于您,则可以使用单个字段的默认值。默认值应始终指定为字符串,但在生成查询时将转换为所需类型。
实体
-
节点
创建节点
let node = Node::new("n", "Profile", None, None);
但您可以将 derive 属性设置到结构
#[derive(Debug, Clone, CypQueSet)]
上,节点将自动生成! -
关系
创建关系
use neo4j_cypher::entity::Relation; let rel = Relation::new(a1.node("n1"), a2.node("n2"), "SUBSCRIBE", None);
在
a1
和a2
中,它们是具有CypQue
继承宏的结构体。
当然,你不仅可以指定一个Props
对象或Label
的向量,而不是使用None
。
模板
neo4j_cypher = { version = "...", features=[ "derive", "templates" ] }
不使用模板的请求示例
use neo4j_cypher::query::match_query::CompOper;
let query = Query::init().r#match(&a1.node("n1").into(), false)
.r#where("name", CompOper::Equal, PropType::str("admin"))
.r#match(&a2.node("n2").into(), false)
.r#where("name", CompOper::Equal, PropType::str("dev"))
.return_many(vec!["n1", "n2"])
.finalize();
使用模板的请求示例
To include templates, you must add `templates` to the **features** dependency sections.
let q = Query::init()
.r#match(&a1.node("n1").into(), false)
.where_eq_str("name", "admin")
.r#match(&a2.node("n2").into(), false)
.where_eq_str("name", "dev")
.return_many(vec!["n1", "n2"])
.finalize();
示例
节点
use std::fmt::Display;
use neo4j_cypher::query::match_query::CompOper;
use neo4j_cypher::CypQue;
/// Example of access levels in the system
#[derive(Debug, Clone)]
enum Perm {
Admin,
User,
}
/// An example of a structure that should be converted into a Neo4j node.
///
/// In your code you use name Account and the Neo4j node label will be Profile.
/// Field `username` will be renamed;
/// Field `secret` will be hidden;
/// Field `perm` will be used as second a node label;
/// Field `level` and `friends` will used a default value if they will be None;
#[derive(Debug, Clone, CypQue)]
#[cypher(rename = "Profile")]
struct Account {
#[cypher(rename = "name")]
username: String,
password: String,
age: i32,
status: Option<String>,
online: bool,
#[cypher(skip)]
secret: u8,
#[cypher(label)]
perm: Perm,
#[cypher(default = "5")]
level: Option<u8>,
#[cypher(default = "['Bob', 'Tom']")]
friends: Option<Vec<String>>,
}
fn main() {
// Init some example struct
let data = Account {
username: String::from("mi1fhunter"),
password: String::from("1234f4321"),
age: 32,
status: None,
online: false,
secret: 1,
perm: Perm::User,
level: None,
friends: Some(vec![
"Bob".to_string(),
"Tom".to_string(),
"Sam".to_string(),
]),
};
// Let's build some query
let query = Query::init()
.create(vec![&a1.node("n").into()])
.r#return("n")
.finalize();
println!("{}", query);
}
因此,查询构建器会自动为您生成这样的查询
CREATE (n:Profile { password: '1234f4321',level: 5,name: 'mi1fhunter',age: 32,friends: ['Bob','Tom','Sam'],online: false })
SET n:User
RETURN n
创建匹配查询的示例
let query = Query::init()
.r#match(&a1.node("n1").into(), false)
.where_eq_str("name", "admin")
.r#match(&a2.node("n2").into(), false)
.where_eq_str("name", "dev")
.return_many(vec!["n1", "n2"])
.finalize();
结果将如下所示
MATCH (n1:Profile) WHERE n1.name = 'admin'
MATCH (n2:Profile) WHERE n2.name = 'dev'
RETURN n1,n2
如果您需要返回某个属性的值或获取另一个var
的名称,您可以写成这样
let query = Query::init()
.create(vec![&model.node("n").into()])
.r#return_field("n", "age")
.finalize();
结果将是
CREATE (n:Profile { name: 'admin',friends: ['Bob','Tom','Sam'],password: '1234f4321',online: false,level: 5,age: 32 })
SET n:User
RETURN n.age
或
let query = Query::init()
.create(vec![&model.node("n").into()])
.r#return("n")
.r#as("node")
.finalize();
结果
CREATE (n:Profile { age: 32,uname: 'mi1fhunter',online: false,level: 5,friends: ['Bob','Tom','Sam'],password: '1234f4321' })
SET n:User
RETURN n AS node
关系
let rel1 = Entity::rel("n1", "n2", "SUBSCRIBE", None);
let rel2 = Entity::rel("n2", "n1", "SUBSCRIBE", None);
let query = Query::init()
.r#match(&a1.node("n1").into(), false)
.where_eq_str("name", "admin")
.r#match(&a2.node("n2").into(), false)
.where_eq_str("name", "dev")
.return_many(vec!["n1", "n2"])
.create(vec![&rel1.into(), &rel2.into()])
.finalize();
结果
MATCH (n1:Profile) WHERE n1.age = 1 AND n1.level = 10
MATCH (n1:Profile) WHERE n1.age = 10
CREATE (n1)-[:SUBSCRIBE]->(n2),
(n2)-[:SUBSCRIBE]->(n1)
依赖关系
~240KB