28个版本
0.6.2 | 2024年5月4日 |
---|---|
0.6.1 | 2024年3月29日 |
0.6.0 | 2023年11月18日 |
0.4.3 | 2023年2月13日 |
0.3.4 | 2021年10月30日 |
#3 in 数据库实现
每月34,502次下载
用于 oma-pm
380KB
3K SLoC
indicium
🔎 针对集合(Vec、HashMap、BTreeMap等)和键值存储的简单内存搜索。具有自动补全功能。
目前有许多令人惊叹的Rust搜索引擎。许多似乎需要编译单独的服务器二进制文件。我希望有一个简单轻量级的库,可以方便地在自己的二进制文件中搜索结构和集合。因此,我制作了indicium
。
尽管indicium
是为Web应用程序而设计的,但它是一种内存搜索,并且不会无限扩展或扩展到云规模(即Facebook或Google规模)。即使在这样的环境中,它仍然是一种方便搜索大量列表(如货币、语言、国家等)的方法。它也非常适用于预期规模有限的应用程序(例如,搜索公司资产列表、企业内联网中用户列表等)。
Indicium可以轻松处理数百万条记录而无需费劲,这得益于Rust的BTreeMap。这个库主要受可用内存的限制。然而,根据数据集的性质以及是否存在多次重复的关键字,性能可能会开始下降。
有什么新功能?
-
发布说明可在GitHub上找到。
-
完整的变更日志可在GitHub上找到。
-
0.6.1
:由于潜在的问题,已移除默认的字符串相似性库eddie
。 -
0.6.0
:针对Live
交互式搜索的上下文模糊匹配修复。在某些情况下,Live
搜索会返回全局结果,而没有正确地观察到maximum_search_results
设置。这个问题已经修复。这将提高性能和用户体验。 -
0.6.0
:新增可选的、默认开启的eddie
功能。当此功能启用时,此库将利用 Ilia Schelokov 的 eddie crate 进行更快的 UTF-8 字符串距离和字符串相似度计算。 -
0.6.0
:新增可选的gxhash
功能。虽然ahash
仍然是默认的哈希器,但启用此功能后,此库将利用 Olivier Giniaux 的前沿 gxhash crate 进行更快的HashMap
和HashSet
哈希。
快速入门指南
在我们的 快速入门指南 示例中,我们将搜索以下 struct
struct MyStruct {
title: String,
year: u16,
body: String,
}
1. 实现索引功能
首先,我们必须使我们的记录可索引。我们将通过为我们的 struct
实现索引功能。想法是返回我们希望索引的每个字段的字符串。示例
use indicium::simple::Indexable;
impl Indexable for MyStruct {
fn strings(&self) -> Vec<String> {
vec![
self.title.clone(),
self.year.to_string(),
self.body.clone(),
]
}
}
别忘了,您可以通过将数字、数字标识符、枚举和其他类型(或其他复杂类型)转换为字符串并将它们包含在返回的 Vec<String>
中来使您的 struct
(或其他复杂类型)可索引。
2. 索引集合
要索引现有集合,我们可以遍历该集合。对于每条记录,我们将将其插入到搜索索引中。这应该类似于以下两个示例
Vec
use indicium::simple::SearchIndex;
let my_vec: Vec<MyStruct> = Vec::new();
// In the case of a `Vec` collection, we use the index as our key. A
// `Vec` index is a `usize` type. Therefore we will instantiate
// `SearchIndex` as `SearchIndex<usize>`.
let mut search_index: SearchIndex<usize> = SearchIndex::default();
my_vec
.iter()
.enumerate()
.for_each(|(index, element)|
search_index.insert(&index, element)
);
HashMap
use std::collections::HashMap;
use indicium::simple::SearchIndex;
let my_hash_map: HashMap<String, MyStruct> = HashMap::new();
// In the case of a `HashMap` collection, we use the hash map's key as
// the `SearchIndex` key. In our hypothetical example, we will use
// MyStruct's `title` as a the key which is a `String` type. Therefore
// we will instantiate `HashMap<K, V>` as HashMap<String, MyStruct> and
// `SearchIndex<K>` as `SearchIndex<String>`.
let mut search_index: SearchIndex<String> = SearchIndex::default();
my_hash_map
.iter()
.for_each(|(key, value)|
search_index.insert(key, value)
);
只要为您的值类型实现了 Indexable
trait,上述示例将索引先前填充的 Vec
或 HashMap
。然而,对于大型集合,建议在将数据插入您的集合(Vec、HashMap 等)的同时将数据插入 SearchIndex
。
建议将目标集合(您的 Vec、HashMap 等)和此 SearchIndex
一起包裹在一个新的 struct
类型中。然后,为这个新的 struct
类型实现 insert
、replace
、remove
等方法,这将更新集合和搜索索引。这将确保您的集合和索引始终同步。
一旦索引被填充,您就可以使用 search
和 autocomplete
方法。
3. 搜索
search
方法将返回键作为搜索结果。然后可以使用每个结果键从其集合中检索完整记录。
基本用法
let mut search_index: SearchIndex<usize> = SearchIndex::default();
search_index.insert(&0, &"Harold Godwinson");
search_index.insert(&1, &"Edgar Ætheling");
search_index.insert(&2, &"William the Conqueror");
search_index.insert(&3, &"William Rufus");
search_index.insert(&4, &"Henry Beauclerc");
let resulting_keys: Vec<&usize> = search_index.search("William");
assert_eq!(resulting_keys, vec![&2, &3]);
// Demonstrating fuzzy matching:
let resulting_keys: Vec<&usize> = search_index.search("Harry");
assert_eq!(resulting_keys, vec![&0]);
搜索只支持精确关键词匹配。对于 Live
搜索,模糊匹配仅应用于最后一个关键词。考虑为用户提供 autocomplete
功能,作为模糊匹配的人性化替代方案。
4. 自动完成
autocomplete
方法将为提供的字符串中的最后一个关键词提供几个自动完成选项。
基本用法
let mut search_index: SearchIndex<usize> =
SearchIndexBuilder::default()
.autocomplete_type(&AutocompleteType::Global)
.build();
search_index.insert(&0, &"apple");
search_index.insert(&1, &"ball");
search_index.insert(&3, &"bird");
search_index.insert(&4, &"birthday");
search_index.insert(&5, &"red");
let autocomplete_options: Vec<String> =
search_index.autocomplete("a very big bi");
assert_eq!(
autocomplete_options,
vec!["a very big bird", "a very big birthday"]
);
// Demonstrating fuzzy matching:
let autocomplete_options: Vec<String> =
search_index.autocomplete("a very big birf");
assert_eq!(
autocomplete_options,
vec!["a very big bird", "a very big birthday"]
);
依赖项
~1.1–1.6MB
~24K SLoC