Indicium

A simple search engine for collections (Vec, HashMap, BTreeMap, etc) and key-value stores. Includes capability for autocomplete.

There are many incredible search engines available for Rust but many seem to require compiling a separate server binary or are too heavy for my use-case. I also couldn't find options for searching structs and collections, hence indicium.

Quick Start Guide

For our Quick Start Guide example, we will be searching inside of the following struct:

rust struct MyStruct { title: String, description: String, }

1. Implementing Indexable

To begin, we must make our record indexable. We'll do this by implementing the Indexable trait for our struct. The idea is to return a String for every field that we would like to be indexed. Example:

```rust use indicium::simple::Indexable;

impl Indexable for MyStruct { fn strings(&self) -> Vec { vec![ self.title.clone(), self.description.clone(), ] } } ```

Don't forget that you may make numbers, numeric identifiers, enums, and other types indexable by converting them to a String and including them in the returned Vec<String>.

2. Indexing a Collection

To index an existing collection, we can iterate over the collection. For each record, we will insert it into the search index. This should look something like these two examples:

```rust use indicium::simple::SearchIndex;

let mut search_index: SearchIndex = SearchIndex::default();

myvec .iter() .enumerate() .foreach(|(index, element)| search_index.insert(&index, element) ); ```

```rust use indicium::simple::SearchIndex;

let mut search_index: SearchIndex = SearchIndex::default();

myhashmap .iter() .foreach(|(key, value)| search_index.insert(&key, value) ); ```

The above examples will index a previously populated Vec or HashMap. However, the preferred method for large collections is to insert into the SearchIndex as you insert into your collection (Vec, HashMap, etc.)

Once the index has been populated, you can use the autocomplete and search functions.

3. Autocompletion

The autocomplete function will provide several autocompletion options for the last partial keyword in the supplied string. The results are returned in lexographic order. Example usage:

```rust let autocompleteoptions: Vec = searchindex.autocomplete(&"big bir".to_string());

asserteq!(autocompleteoptions, vec!["big bird", "big birthday"]); ```

With a bit of imagination you could create a typeahead microservice for your web application using a crate like actix-web or rocket.

4. Searching

The search function will return keys as the search results. Each resulting key can then be used to retrieve the corresponding record from its collection. Search keywords must be an exact match. The logical conjuction for multiple keywords is or. The results are returned in order of descending relevance. Example usage:

```rust let resultingkeys: Vec = searchindex.keywordsearch(&"Helicopter".tostring());

asserteq!(resultingkeys, Some(vec![1])); ```

Since search only supports exact keyword matches and does not fuzzy matching, consider implementing autocomplete for your search.

The Keyword Methods

The keyword_autocomplete and keyword_search methods work on strings that are expected to contain only a single keyword (as opposed to strings containing multiple keywords.) For small collections, these methods might be a lighter-weight alternative to their big brothers.

Autocompletion

The keyword_autocomplete function will return several keywords that begin with the partial keyword provided by the caller. Example usage:

```rust let autocompleteoptions: Vec = searchindex.keywordautocomplete(&"ass".tostring());

asserteq!(autocompleteoptions, vec!["assassin", "assistance"]); ```

Searching

The keyword_search function will return keys for indexed records that match the keyword provided by the caller. Each resulting key can then be used to retrieve the corresponding record from its collection. The search keyword must be an exact match. The results are returned in undefined order. Example usage:

```rust let resultingkeys: Vec = searchindex.keywordsearch(&"Helicopter".tostring());

asserteq!(resultingkeys, Some(vec![&1])); ```

Since search only supports exact keyword matches and does not fuzzy matching, consider implementing autocomplete for your search.