Struct dodo::Index[][src]

pub struct Index<T, S, R> { /* fields omitted */ }

Index of values.

Indexes are usually paired with collections to make some queries faster. They allow to quickly locate an entity id without having to search the whole collection.

Example

use dodo::prelude::*;

type PersonCollection = Collection<Person, Directory, JsonSerializer>;
type NameIndex = Index<String, Directory, JsonSerializer>;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut collection = PersonCollection::new(Directory::new(&collection_path)?);
    let mut index = NameIndex::new(Directory::new(&index_path)?);

    let mut person1 = Person::new("John Smith");
    collection.insert(&mut person1)?;
    index.add(person1.id.unwrap(), &person1.name)?;
    let mut person2 = Person::new("John Smith");
    collection.insert(&mut person2)?;
    index.add(person2.id.unwrap(), &person2.name)?;
    let mut person3 = Person::new("Mary Smith");
    collection.insert(&mut person3)?;
    index.add(person3.id.unwrap(), &person3.name)?;

    // Ids of all "John Smith"s.
    let ids = index.find("John Smith")?;

    println!("{:?}", ids);

    Ok(())
}

Storage optimisations

Like collections, indexes assume to have complete control of their storage, but if needed, they can share a common storage as long as each index have a different id assigned to it. See the with_index function for details.

Serializer

Like collections, indexes need a serializer to serializer the index data.

Other considerations

You should only index basic types, like numbers or strings. You can still index any value as long as it implements Hash, ToString and FromStr, but it should be considerez bad practice.

Implementations

impl<T, S, R> Index<T, S, R> where
    S: Storage,
    R: Serializer
[src]

pub fn new(storage: S) -> Self[src]

Create a new index, using provided storage.

When created like this, the index assumes that it has complete control over the storage and stores the index data a single file named 00000000-0000-0000-0000-000000000000. If you want to reuse a storage for multiple indexes, see the with_id function.

Examples

use dodo::prelude::*;

type NameIndex = Index<String, Directory, JsonSerializer>;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut index = NameIndex::new(Directory::new(&index_path)?);

    Ok(())
}

pub fn with_id(storage: S, id: Uuid) -> Self[src]

Create a new index inside provided storage, using assigned id.

When created like this, the index knows that it does not have complete control over the storage and stores the index data a single file named after his assigned id.

Examples

use dodo::prelude::*;

type NameIndex = Index<String, Directory, JsonSerializer>;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();
    let mut index = NameIndex::with_id(Directory::new(&index_path)?, id);

    Ok(())
}

pub fn find<Q: ?Sized>(&self, value: &Q) -> Result<HashSet<Uuid>> where
    T: Borrow<Q>,
    Q: Hash + ToString
[src]

Returns all ids corresponding to the given value.

Returns an error if not found.

Examples

let ids = index.find("John Smith");

match ids {
    Ok(ids) => println!("Found!"),
    Err(e) if e.is_not_found() => println!("Not found!"),
    Err(_) => println!("Other error!")
}

pub fn find_all(&self) -> Result<IndexIterator<T>> where
    T: FromStr
[src]

Provide an iterator through the index entries.

This can be pretty useful to query all index values.

Examples

let names: Vec<String> = index.find_all()?.map(|(ids, name) : (HashSet<Uuid>, String)| name).collect();

println!("{:#?}", names);

pub fn add(&mut self, id: Uuid, value: &T) -> Result<()> where
    T: Hash + ToString
[src]

Add value to the index, assigned to provided id.

The index doesn’t keep multiple copies of the same key/value pair (i.e there are no duplicates).

Examples

let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();
let value = "John Smith".into();

index.add(id, &value)?;

pub fn remove<Q: ?Sized>(&mut self, id: Uuid, value: &Q) -> Result<bool> where
    T: Borrow<Q>,
    Q: Hash + ToString
[src]

Remove id/value pair from index.

This does not fail if the pair doesn’t exist in the index. Instead, this returns a boolean : if true, the pair was removed, and if false, the pair was not found.

Examples

let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();
let value : String = "John Smith".into();
index.add(id, &value)?;

assert!(index.remove(id, &value)?);

pub fn remove_id(&mut self, id: Uuid) -> Result<bool>[src]

Remove id from index.

This has some serious performance implications as it must traverse the entire index and should only be used when unavoidable.

This does not fail if the id doesn’t exist in the index. Instead, this returns a boolean : if true, the id was removed, and if false, the id was not found.

Examples

let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();
let value : String = "John Smith".into();
index.add(id, &value)?;

assert!(index.remove_id(id)?);

pub fn remove_value<Q: ?Sized>(&mut self, value: &Q) -> Result<HashSet<Uuid>> where
    T: Borrow<Q>,
    Q: Hash + ToString
[src]

Remove value from index and all related ids.

Returns the ids assigned to the removed value. Note that theses ids can still be in the index, but assigned to others values.

This does not fail if the value doesn’t exist in the index. In that case, this returns an empty set of ids.

Examples

let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();
let value : String = "John Smith".into();
index.add(id, &value)?;

let ids = index.remove_value(&value)?;
assert!(ids.contains(&id));

pub fn clear(&mut self) -> Result<()>[src]

Remove every value in this index.

Everything in this index will be deleted. Use at your own risks.

Examples

index.add(id, &value)?;

index.clear()?;

Trait Implementations

impl<T: Clone, S: Clone, R: Clone> Clone for Index<T, S, R>[src]

impl<T: Debug, S: Debug, R: Debug> Debug for Index<T, S, R>[src]

Auto Trait Implementations

impl<T, S, R> RefUnwindSafe for Index<T, S, R> where
    R: RefUnwindSafe,
    S: RefUnwindSafe,
    T: RefUnwindSafe

impl<T, S, R> Send for Index<T, S, R> where
    R: Send,
    S: Send,
    T: Send

impl<T, S, R> Sync for Index<T, S, R> where
    R: Sync,
    S: Sync,
    T: Sync

impl<T, S, R> Unpin for Index<T, S, R> where
    R: Unpin,
    S: Unpin,
    T: Unpin

impl<T, S, R> UnwindSafe for Index<T, S, R> where
    R: UnwindSafe,
    S: UnwindSafe,
    T: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<V, T> VZip<V> for T where
    V: MultiLane<T>,