我想在一个内存数据库中,使用BTreeMap作为索引,支持多个关键字。就像这样:
let mut map = BTreeMap::new();
map.insert(("a".to_string(), "x".to_string()), "ax".to_string());
map.insert(("a".to_string(), "y".to_string()), "ay".to_string());
现在我的问题是,实际上查询这个的最佳方式是什么?例如,我想要获取(“a”,*),也就是所有以“a”为第一个键并且第二个键任意的条目。
我尝试了类似于以下内容:
use std::{collections::{BTreeMap}, cmp::Ordering};
use std::ops::Bound::{Included, Unbounded};
#[derive(Clone, Debug, Hash)]
pub enum StringKey {
Exact(String),
Any,
}
impl PartialOrd for StringKey {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self, other) {
(StringKey::Exact(a), StringKey::Exact(b)) => Some(a.cmp(b)),
(StringKey::Exact(_), StringKey::Any) => Some(Ordering::Equal),
(StringKey::Any, StringKey::Exact(_)) => Some(Ordering::Equal),
(StringKey::Any, StringKey::Any) => Some(Ordering::Equal),
}
}
}
impl Ord for StringKey {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}
impl PartialEq for StringKey {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Exact(a), Self::Exact(b)) => a == b,
(Self::Exact(_), Self::Any) => true,
(Self::Any, Self::Exact(_)) => true,
(Self::Any, Self::Any) => true,
}
}
}
impl Eq for StringKey {
}
fn main() {
let mut map = BTreeMap::new();
map.insert((StringKey::Exact("a".to_string()), StringKey::Exact("x".to_string())), "ax".to_string());
map.insert((StringKey::Exact("a".to_string()), StringKey::Exact("y".to_string())), "ay".to_string());
map.insert((StringKey::Exact("b".to_string()), StringKey::Exact("x".to_string())), "bx".to_string());
let query = (StringKey::Exact("a".to_string()), StringKey::Any);
// Would be easier to do (Included(query), Included(query)), but that only returns one item
let iter = map.range((Included(query.clone()), Unbounded));
for (key, value) in iter {
if key > &query {
return;
}
println!("{:?} {:?}", key, value);
}
}
打印哪些内容
(Exact("a"), Exact("x")) "ax"
(Exact("a"), Exact("y")) "ay"
这么做是有效的,但问题在于我违反了 Ord/Eq 规则(例如 StringKey::Exact("a") == StringKey::Any == StringKey::Exact("b")),这似乎不是正确的方法。而且当我希望在代码的其他部分中将 StringKey 存储在 HashMap 中时,由于实现 Eq 的方式,这并不真正起作用。
那么,有更好的方法吗?
感谢任何帮助!