การค้นหาในหน่วยความจำที่เรียบง่ายสำหรับคอลเลกชัน ( Vec , HashMap , BTreeMap ฯลฯ ) และร้านค้าคีย์-ค่า คุณสมบัติการเติมเงินอัตโนมัติและการจับคู่ฟัซซี่
มีเครื่องมือค้นหาที่น่าทึ่งมากมายสำหรับสนิม หลายคนดูเหมือนจะต้องรวบรวมไบนารีเซิร์ฟเวอร์แยกต่างหาก ฉันต้องการบางสิ่งบางอย่างที่เรียบง่ายและน้ำหนักเบา-ลังที่ใช้งานง่ายที่สามารถค้นหาโครงสร้างและคอลเลกชันภายในไบนารีของฉันเองได้อย่างสะดวกสบาย ดังนั้นฉันจึงสร้าง indicium
ในขณะที่ indicium ถูกสร้างขึ้นด้วยเว็บแอพในใจมันเป็นการค้นหาในหน่วยความจำและไม่ได้ปรับขนาดอย่างไม่มีกำหนดหรือขนาดคลาวด์ (เช่น Facebook หรือขนาดของ Google) แม้ในสภาพแวดล้อมเช่นนี้มันยังคงเป็นวิธีที่สะดวกในการค้นหารายการขนาดใหญ่ (เช่นสกุลเงินภาษาประเทศ ฯลฯ ) นอกจากนี้ยังเหมาะสำหรับแอปพลิเคชันที่มีการ จำกัด มาตราส่วนที่คาดการณ์ไว้ (เช่นการค้นหารายการสินทรัพย์ของ บริษัท
Informium สามารถจัดการบันทึกหลายล้านรายการได้โดยไม่ต้องมีเหงื่อออกจาก BTREEMAP ของ Rust ลังนี้ถูก จำกัด โดยหน่วยความจำที่มีอยู่เป็นหลัก อย่างไรก็ตามขึ้นอยู่กับลักษณะที่ตั้งค่าข้อมูลของคุณและหากมีคำหลักที่ทำซ้ำหลายครั้งประสิทธิภาพอาจเริ่มลดลง ณ จุดหนึ่ง
กำหนดค่าการพึ่งพาในไฟล์ Cargo.toml ของโครงการของคุณ:
[ dependencies ]
indicium = " 0.6 "โน้ตปล่อยมีอยู่ใน GitHub
บันทึกการเปลี่ยนแปลงเต็มรูปแบบมีอยู่ใน GitHub
สำหรับตัวอย่าง คู่มือเริ่มต้นอย่างรวดเร็ว ของเราเราจะค้นหาภายใน struct ต่อไปนี้:
struct MyStruct {
title : String ,
year : u16 ,
body : String ,
} ในการเริ่มต้นเราต้องทำดัชนีบันทึกของเรา เราจะทำสิ่งนี้โดยใช้คุณสมบัติ Indexable สำหรับ struct ของเราได้ แนวคิดคือการส่งคืน 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 ( ) ,
]
}
} อย่าลืมว่าคุณอาจสร้างตัวเลขตัวระบุตัวเลข enums และประเภทอื่น ๆ ใน struct (หรือประเภทที่ซับซ้อนอื่น ๆ ) ที่สามารถจัดทำดัชนีโดยแปลงเป็น String และรวมไว้ใน Vec<String>
ในการจัดทำดัชนีคอลเลกชันที่มีอยู่เราสามารถทำซ้ำได้มากกว่าคอลเลกชัน สำหรับแต่ละระเบียนเราจะแทรกลงในดัชนีการค้นหา สิ่งนี้ควรมีลักษณะเหมือนสองตัวอย่างนี้:
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 ที่มีประชากรก่อนหน้านี้ก่อนหน้านี้ อย่างไรก็ตามวิธีที่ต้องการสำหรับคอลเลกชันขนาดใหญ่คือการ insert ลงใน SearchIndex ในขณะที่คุณแทรกลงในคอลเลกชันของคุณ (VEC, HashMap ฯลฯ )
ขอแนะนำให้ห่อคอลเลกชันเป้าหมายของคุณ ( 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" ]
) ;ลังนี้ได้รับการดูแลอย่างอดทน ลังนี้ทำในสิ่งที่คาดว่าจะทำและทำได้ดีในความคิดของฉัน ไม่คาดว่าจะมีการอัปเดตบ่อยครั้ง