简单的内存搜索集合( Vec , HashMap , BTreeMap等)和钥匙值商店。功能自动完成和模糊匹配。
Rust有许多令人难以置信的搜索引擎。许多似乎需要编译单独的服务器二进制文件。我想要一些简单且轻巧的东西 - 一种易于使用的板条箱,可以方便地搜索我自己的二进制中的结构和收藏。所以,我做了indicium 。
考虑到Web应用程序的indicium ,这是一种内存搜索,并且不会无限地扩展到云大小(即Facebook或Google大小)。即使在这样的环境中,它仍然是搜索大量列表(例如货币,语言,国家等)的便捷方法。对于有预期的规模限制的应用程序也非常有用(即搜索公司资产列表,公司Interanet中的用户列表,等等)
由于Rust的Btreemap,很容易处理数百万张唱片而不会破坏汗水。该板条箱主要受可用内存的限制。但是,根据您的数据集的性质以及多次重复的关键字,在某个时候,性能可能会开始降级。
配置项目货物中的依赖项: Cargo.toml文件:
[ dependencies ]
indicium = " 0.6 "发行说明可在GitHub上找到。
完整的更改日志可在GitHub上获得。
对于我们的快速启动指南示例,我们将在以下struct内进行搜索:
struct MyStruct {
title : String ,
year : u16 ,
body : String ,
} 首先,我们必须使我们的记录索引。我们将通过为我们的struct实现Indexable特征来做到这一点。这个想法是返回我们希望被索引的每个字段的String 。例子:
use indicium :: simple :: Indexable ;
impl Indexable for MyStruct {
fn strings ( & self ) -> Vec < String > {
vec ! [
self .title.clone ( ) ,
self .year.to_string ( ) ,
self .body.clone ( ) ,
]
}
}不要忘记,您可以通过将它们转换为String并将其包含在返回的Vec<String>中,可以在struct (或其他复杂类型)中制作数字,数字标识符,枚举和其他类型。
要索引现有的集合,我们可以迭代集合。对于每个记录,我们将其将其插入搜索索引中。这应该看起来像这两个示例:
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 )
) ; 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性状,上述示例就会索引先前填充的Vec或HashMap 。但是,大型集合的首选方法是将您插入集合(VEC,HashMap等)时insert SearchIndex index中。
建议包装您的目标集合(您的Vec , HashMap等),并将此SearchIndex一起使用新的struct类型。然后,实现insert , replace , remove等。该新struct类型的方法将同时更新集合和搜索索引。这将确保您的收集和索引始终同步。
索引填充后,您可以使用search和autocomplete方法。
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功能,作为模糊匹配的符合人体工程学的替代方案。
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" ]
) ;该板条箱被动地维护。在我看来,这个板条箱做了它的期望,并且做得很好。频繁的更新不会预期。