5 个不稳定版本
0.3.1 | 2024年3月24日 |
---|---|
0.3.0 | 2024年3月1日 |
0.2.0 | 2023年8月12日 |
0.1.1 | 2023年8月7日 |
0.1.0 | 2023年8月6日 |
#310 在 数据库接口
每月204 次下载
64KB
1K SLoC
cypher-dto
用于在Neo4j中处理数据传输对象的特性和宏集合。
简要概述
use cypher_dto::{Node, Relation};
#[derive(Node)]
struct Person {
name: String
}
#[derive(Relation)]
struct Knows {
since: u16
}
let alice = Person::new("Alice");
let bob = Person::new("Bob");
let knows = Knows::new(2020);
let graph = neo4rs::Graph::new(/*...*/);
let query: neo4rs::Query = alice.create();
graph.execute(query);
let alice = alice.into_builder().name("Allison").build();
let query = alice.update();
graph.execute(query);
let query = knows.create(RelationBound::Match(&alice), RelationBound::Create(&bob));
graph.execute(query);
示例
基本用法
use cypher_dto::Node;
use neo4rs::Query;
#[derive(Node)]
struct Person {
id: String, // Inferred to be the only #[id] field.
name: String,
#[name = "zip_code"]
zip: String,
}
assert_eq!(Person::typename(), "Person");
assert_eq!(Person::field_names(), &["id", "name", "zip_code"]);
// For building parameterized cypher queries...
assert_eq!(Person::as_query_fields(), "id: $id, name: $name, zip_code: $zip_code");
assert_eq!(Person::as_query_obj(), "Person { id: $id, name: $name, zip_code: $zip_code }");
let person = Person::new("123", "John", "12345");
// Unitary CRUD operations are provided for convenience.
let query = person.create();
// Equivalent to:
let mut query = Query::new(format!(
"CREATE (n:{})",
Person::as_query_obj()
));
query = person.add_values_to_params(query, None, StampMode::Create);
#[derive(Clone, Debug, PartialEq, Relation)]
struct Knows;
assert_eq!(Knows::typename(), "KNOWS");
多值标识符
use cypher_dto::Node;
use neo4rs::Query;
#[derive(Node)]
struct Company {
#[id]
name: String,
#[id]
state: String,
phone: String,
}
let company = Company::new("Acme", "CA", "555-555-5555");
let id = company.identifier();
assert_eq!(id.name(), "Acme");
assert_eq!(id.state(), "CA");
assert_eq!(id, CompanyId::new("Acme", "CA"));
assert_eq!(CompanyId::typename(), "Company");
assert_eq!(CompanyId::field_names(), &["name", "state"]);
let query = id.read();
// Equivalent to:
let mut query = Query::new(format!(
"MATCH (n:{}) RETURN n",
CompanyId::as_query_obj()
));
query = id.add_values_to_params(query, None, StampMode::Read);
构建器、new和getter
-
生成的
::new()
方法将接受&str
作为String
字段的参数,以及&[T]
作为Vec<T>
字段的参数。 -
文档注释被复制到结构体的getter、
FooId
结构体的getter以及FooBuilder
结构体的方法中。
#[derive(Node)]
struct Person {
/// This comment is copied to the getter, the Id getter, and the builder method.
name: String,
}
let p = Person::new("John");
let p = p.into_builder().name("Ferris").build();
assert_eq!(p.name(), "Ferris");
时间戳
内置了对特殊时间戳字段的支持:created_at
和 updated_at
,created
和 updated
,或这四个中的任意一个。
use cypher_dto::timestamps;
#[timestamps]
struct Person {
name: String,
}
// Adds two fields:
// created_at: Option<DateTime<Utc>>,
// updated_at: Option<DateTime<Utc>>,
#[timestamps = "short"]
struct Person {
name: String,
}
// Adds two fields:
// created: Option<DateTime<Utc>>,
// updated: Option<DateTime<Utc>>,
#[timestamps = "updated_at"]
struct Person {
name: String,
}
// Adds one field:
// updated_at: Option<DateTime<Utc>>,
时间戳字段与其他字段的处理略有不同
- 它们不是生成的
::new()
方法的参数。 - 它们有时在
::to_query_fields()
中有硬编码的值。- 使用
to_query_fields()
并传递StampMode::Create
将在查询中使用datetime()
而不是例如$created_at
。
- 使用
Option<DateTime<Utc>>
用来代替 DateTime<Utc>
,以便在创建新实例时,在它存在于数据库之前,字段可以设置为 None
。
有关宏变体的更多详细信息,请参阅 cypher-dto-macros 库。
单元CRUD操作
此库认为非平凡查询应手动管理,但它确实提供了基本的CRUD操作以方便使用。
#[derive(Node)]
和 #[derive(Relation)]
结构体将获得 create
和 update
方法,而相应的 FooId
结构体会获得 read
和 delete
方法,所有这些方法都返回一个 neo4rs::Query
。
这些方法甚至不需要任何参数,除了创建关系,需要知道它之间的起始和结束节点是否需要创建或已经存在。
use cypher_dto::{Node, Relation};
#[derive(Node)]
Person {
name: String,
}
#[derive(Clone, Debug, PartialEq, Relation)]
struct Knows;
let alice = Person::new("Alice");
let bob = Person::new("Bob");
let knows = Knows; // Relations can have fields and ids too.
let query = knows.create(RelationBound::Create(&alice), RelationBound::Create(&bob));
节点标签
虽然可以使用 neo4rs::Node::labels(
从数据库中读取节点的当前标签,但此库提供了一种定义结构体应使用的标签的方法。然后,这些标签将由内置的CRUD操作使用。
#[derive(Node)]
#[labels("Person", "Employee")]
Person {
name: String,
}
let person = Person::new("Alice");
assert_eq!(person.labels(), &["Person", "Employee"]);
依赖关系
~14–27MB
~491K SLoC