Eine einfache In-Memory-Suche nach Sammlungen ( Vec , HashMap , BTreeMap usw.) und Schlüsselwertgeschäften. Verfügt über Autoperation und Fuzzy -Matching.
Es gibt viele unglaubliche Suchmaschinen für Rost. Viele scheinen ein separates Server -Binärer zu erfordern. Ich wollte etwas Einfaches und Leichtes-eine benutzerfreundliche Kiste, die bequem Strukturen und Sammlungen in meinem eigenen Binärer durchsuchen könnte. Also habe ich indicium gemacht.
Während indicium im Hinblick auf Web-Apps hergestellt wurde, handelt es sich um eine In-Memory-Suche und weder auf unbestimmte Zeit noch auf Cloud-Größe (dh Facebook oder Google-Größe). Selbst in einer solchen Umgebung wäre es immer noch eine bequeme Möglichkeit, große Listen zu durchsuchen (wie Währungen, Sprachen, Länder usw.). Es ist auch hervorragend für Anwendungen, bei denen ein erwartete Skalierungsgrenze vorhanden ist (dh durchsucht eine Liste von Unternehmensvermögen, Liste der Benutzer in einem Unternehmensintranet usw.).
Indicium kann dank Rusts BTeMap leicht Millionen von Rekorde abwickeln, ohne sich ins Schwitzen zu bringen. Diese Kiste ist in erster Linie durch den verfügbaren Speicher begrenzt. Abhängig von der Art Ihrer Datenmenge und wenn Keywords, die sich um ein Vielfaches wiederholen, kann die Leistung zu einem Punkt zu degradieren.
Konfigurieren Sie die Abhängigkeiten in der Cargo.toml -Datei Ihres Projekts:
[ dependencies ]
indicium = " 0.6 "Versionshinweise finden Sie auf GitHub.
Das vollständige Änderungsprotokoll ist auf GitHub verfügbar.
Für unser Beispiel für ein Quick Start Guide werden wir in der folgenden struct suchen:
struct MyStruct {
title : String ,
year : u16 ,
body : String ,
} Zunächst müssen wir unser Rekord indexierbar machen. Wir werden dies tun, indem wir das Indexable Merkmal für unsere struct implementieren. Die Idee ist, eine String für jedes Feld zurückzugeben, das wir indexiert werden möchten. Beispiel:
use indicium :: simple :: Indexable ;
impl Indexable for MyStruct {
fn strings ( & self ) -> Vec < String > {
vec ! [
self .title.clone ( ) ,
self .year.to_string ( ) ,
self .body.clone ( ) ,
]
}
} Vergessen Sie nicht, dass Sie Zahlen, numerische Kennungen, Aufzüge und andere Typen in Ihrer struct (oder anderen komplexen Typen) indexierbar erstellen können, indem sie in eine String konvertiert und in die zurückgegebene Vec<String> aufgenommen werden.
Um eine vorhandene Sammlung zu indizieren, können wir die Sammlung itererieren. Für jeden Datensatz werden wir es in den Suchindex einfügen. Dies sollte ungefähr wie diese beiden Beispiele aussehen:
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 )
) ; Solange das Indexable Merkmal für Ihren Werttyp implementiert wurde, werden die obigen Beispiele einen zuvor besiedelten Vec oder HashMap indexiert. Die bevorzugte Methode für große Sammlungen besteht jedoch darin, in den SearchIndex insert , während Sie in Ihre Sammlung einfügen (VEC, HashMap usw.).
Es wird empfohlen, Ihre Zielsammlung (Ihre Vec , HashMap usw.) und diesen SearchIndex in einem neuen struct zusammenzupacken. Implementieren Sie dann die Methoden zum insert , replace , remove usw. für diesen neuen struct , der sowohl den Sammel- als auch den Suchindex aktualisiert. Dadurch wird sichergestellt, dass sowohl Ihre Sammlung als auch Ihr Index immer synchronisiert sind.
Sobald der Index besiedelt ist, können Sie die search und autocomplete -Methoden verwenden.
Die search gibt Tasten als Suchergebnisse zurück. Jede resultierende Taste kann dann verwendet werden, um den vollständigen Datensatz aus seiner Sammlung abzurufen.
Grundnutzung:
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 ] ) ; Die Suche nur unterstützt genaue Schlüsselwort -Übereinstimmungen. Für Live -Suchanfragen wird das Fuzzy -Matching nur auf das letzte Schlüsselwort angewendet. Überlegen Sie sich, dass Sie Ihren Benutzern die autocomplete Funktion als ergonomische Alternative zu Fuzzy -Matching anbieten.
Die autocomplete Vervollständigungsmethode bietet mehrere Autokapostionsoptionen für das letzte Schlüsselwort in der angegebenen Zeichenfolge.
Grundnutzung:
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" ]
) ;Diese Kiste ist passiv aufrechterhalten. Diese Kiste macht meiner Meinung nach das, was es erwartet hat, und macht es ziemlich gut. Es werden häufige Updates nicht erwartet.