Uma busca simples na memória por coleções ( Vec , HashMap , BTreeMap , etc.) e lojas de valor-chave. Apresenta conclusão automática e correspondência difusa.
Existem muitos mecanismos de busca incríveis disponíveis para a ferrugem. Muitos parecem exigir a compilação de um servidor separado. Eu queria algo simples e leve-uma caixa fácil de usar que pudesse pesquisar convenientemente estruturas e coleções em meu próprio binário. Então, eu fiz indicium .
Embora indicium tenha sido feito com aplicativos da Web em mente, é uma pesquisa na memória e não escala indefinidamente ou para o tamanho da nuvem (ou seja, o Facebook ou o tamanho do Google). Mesmo em tal ambiente, ainda seria uma maneira conveniente de pesquisar grandes listas (como moedas, idiomas, países etc.), também é ótimo para aplicativos onde há um limite de escala previsto (ou seja, pesquisando uma lista de ativos da empresa, lista de usuários em uma intranet corporativa etc.)
O Indicium pode facilmente lidar com milhões de discos sem suar a camisa graças ao BreeMap de Rust. Esta caixa é limitada principalmente pela memória disponível. No entanto, dependendo da natureza do seu conjunto de dados e se houver palavras-chave repetidas muitas vezes, o desempenho poderá começar a se degradar em um ponto.
Configure as dependências na Cargo.toml do seu projeto.
[ dependencies ]
indicium = " 0.6 "As notas de lançamento estão disponíveis no Github.
O log de alterações completo está disponível no GitHub.
Para nosso exemplo de guia de início rápido , procuraremos dentro da seguinte struct :
struct MyStruct {
title : String ,
year : u16 ,
body : String ,
} Para começar, devemos tornar nosso registro indexível. Faremos isso implementando a característica Indexable para nossa struct . A idéia é retornar uma String para todos os campos que gostaríamos de ser indexados. Exemplo:
use indicium :: simple :: Indexable ;
impl Indexable for MyStruct {
fn strings ( & self ) -> Vec < String > {
vec ! [
self .title.clone ( ) ,
self .year.to_string ( ) ,
self .body.clone ( ) ,
]
}
} Não se esqueça que você pode criar números, identificadores numéricos, enumes e outros tipos em sua struct (ou outros tipos complexos) indexíveis, convertendo -os em uma String e incluí -los no Vec<String> retornado.
Para indexar uma coleção existente, podemos iterar sobre a coleção. Para cada registro, vamos inseri -lo no índice de pesquisa. Isso deve se parecer com esses dois exemplos:
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 )
) ; Enquanto a característica Indexable foi implementada para o seu tipo de valor, os exemplos acima indexarão um Vec ou HashMap previamente povoado. No entanto, o método preferido para grandes coleções é insert no SearchIndex enquanto você insere em sua coleção (VEC, Hashmap, etc.)
É recomendável envolver sua coleção de destino (seu Vec , HashMap , etc.) e este SearchIndex em um novo tipo struct . Em seguida, implemente a insert , replace , remove , etc. Métodos para esse novo tipo de struct que atualizará o índice de coleta e pesquisa. Isso garantirá que sua coleção e índice sejam sempre sincronizados.
Depois que o índice for preenchido, você pode usar os métodos de search e autocomplete .
O método search retornará as chaves como os resultados da pesquisa. Cada chave resultante pode ser usada para recuperar o registro completo de sua coleção.
Uso básico:
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 ] ) ; A pesquisa suporta apenas correspondências de palavras -chave exatas. Para pesquisas Live , a correspondência difusa é aplicada apenas à última palavra -chave. Considere fornecer o recurso autocomplete para seus usuários como uma alternativa ergonômica à correspondência difusa.
O método autocomplete fornecerá várias opções de conclusão automática para a última palavra -chave na sequência fornecida.
Uso básico:
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" ]
) ;Esta caixa é mantida passivamente. Esta caixa faz o que deve fazer e faz muito bem, na minha opinião. Atualizações frequentes não são esperadas.