3 个不稳定版本
0.2.0 | 2022 年 12 月 8 日 |
---|---|
0.2.0-rc.1 | 2022 年 11 月 28 日 |
0.1.0 | 2022 年 1 月 18 日 |
#1192 in 数据库接口
33KB
588 行
joinable
joinable
定义了用于连接值迭代器的特质。就像您可以在 SQL 中连接两个数据库表以生成匹配的记录一样,joinable
提供了在 Rust 代码中实现相同功能的简单功能。
Joinable
特质允许您连接左右两侧,对于内部连接产生 (&L, &R)
,对于外部连接产生 (&L, Option<&R>)
。由于相同的左值可能会因为多个右匹配而多次产生,Joinable
使用来自 LHS 的借用值
use joinable::Joinable;
let customers = get_customers();
let orders = get_orders();
let it = customers
.iter()
.outer_join(&orders[..], |c, o| c.id.cmp(&o.customer_id));
JoinableGrouped
特质通过将右侧值收集到 Vec
中来连接左右两侧。这个 '分组' 版本最多为每个左值产生一次,因此它可以拥有左边的迭代器
use joinable::JoinableGrouped;
let customers = get_customers();
let orders = get_orders();
let it = customers
.into_iter()
.outer_join_grouped(&orders[..], |c, o| c.id.cmp(&o.customer_id));
for (cust, ords) in it {
if ords.is_empty() {
println!("Customer '{}' has no orders", cust.name);
} else {
let total_spend = ords.iter().map(|o| o.amount_usd).sum::<f32>();
println!("Customer '{}' has spent ${:0.2}", cust.name, total_spend);
}
}
JoinableGrouped
还公开了 SEMIJOIN 和 ANTISEMIJOIN 功能,分别只产生在右侧找到或不找到匹配的左侧的行
use joinable::JoinableGrouped;
let customers = get_customers();
let orders = get_orders();
let customers_with_orders : Vec<&Customer> = customers
.iter()
.semi_join(&orders[..], |c, o| c.id.cmp(&o.customer_id))
.collect();
let customers_without_orders : Vec<Customer> = customers
.into_iter()
.anti_join(&orders[..], |c, o| c.id.cmp(&o.customer_id))
.collect();
搜索谓词
对于所有连接,搜索谓词的类型为 Fn(&L, &R) -> std::cmp::Ordering
;也就是说,给定一些来自左右两侧的值,您的谓词必须确定这两个值如何比较。如果用于匹配的类型没有实现 PartialOrd
,您可以简单地检查相等并返回 Ordering::Equal
/某个非 Equal
值。
使用 RHS::Sorted
枚举 RHS
包装了连接的右侧。默认情况下,RHS
假设您的数据是无序的
let customers_with_orders : Vec<&Customer> = customers
.iter()
.semi_join(&orders[..], |c, o| c.id.cmp(&o.customer_id))
// ^^^^^^ orders is implicitly converted Into<RHS>
.collect();
如果您的用例允许并且这样做有意义,您可以按照搜索谓词对右侧进行排序,使得搜索可以在 O(ln n) 的时间复杂度内进行二分搜索,而不是线性的 O(n)
let customers_with_orders : Vec<&Customer> = customers
.iter()
.semi_join(RHS::Sorted(&orders[..]), |c, o| c.id.cmp(&o.customer_id))
// ^^^^^^^^^^^^^^^^^^^^^^^^ signal that orders is sorted by customer_id
.collect();
joinable
假设您的有序数据是按 升序 排序的。如果您有降序排序的数据,则可以反转排序顺序。