diff --git a/meilidb-data/src/cf_tree.rs b/meilidb-data/src/cf_tree.rs index 791f0de81..c15bbbcbb 100644 --- a/meilidb-data/src/cf_tree.rs +++ b/meilidb-data/src/cf_tree.rs @@ -93,6 +93,13 @@ impl CfTree { let mut iter = self.index.db.iterator_cf(cf, IteratorMode::End)?; Ok(iter.next().map(|(key, _)| key)) } + + pub fn prefix_iterator

(&self, prefix: P) -> RocksDbResult + where P: AsRef<[u8]>, + { + let cf = self.index.db.cf_handle(&self.index.name).unwrap(); + self.index.db.prefix_iterator_cf(cf, prefix) + } } pub struct CfIter<'a> { diff --git a/meilidb-data/src/database/index/common_index.rs b/meilidb-data/src/database/index/common_index.rs new file mode 100644 index 000000000..d102bb3bb --- /dev/null +++ b/meilidb-data/src/database/index/common_index.rs @@ -0,0 +1,68 @@ +use serde::de::DeserializeOwned; +use serde::Serialize; +use super::Error; +use std::marker::PhantomData; + +#[derive(Clone)] +pub struct CommonIndex(pub crate::CfTree); + +impl CommonIndex { + pub fn get(&self, key: K) -> Result, Error> + where T: DeserializeOwned, + K: AsRef<[u8]>, + { + let raw = match self.0.get(key)? { + Some(raw) => raw, + None => return Ok(None), + }; + let data = bincode::deserialize(&raw)?; + Ok(Some(data)) + } + + pub fn set(&self, key: K, data: &T) -> Result<(), Error> + where T: Serialize, + K: AsRef<[u8]>, + { + let raw = bincode::serialize(data)?; + self.0.insert(key, &raw)?; + Ok(()) + } + + pub fn prefix_iterator(&self, prefix: P) -> Result, Error> + where T: DeserializeOwned, + P: AsRef<[u8]>, + { + let iter = self.0.prefix_iterator(prefix)?; + Ok(SerializedIterator { iter, _marker: PhantomData }) + } +} + +pub struct SerializedIterator<'a, T> { + iter: rocksdb::DBIterator<'a>, + _marker: PhantomData, +} + +impl Iterator for SerializedIterator<'_, T> +where T: DeserializeOwned, +{ + type Item = (String, T); + + fn next(&mut self) -> Option { + let (raw_key, raw_value) = match self.iter.next() { + Some((key, value)) => (key, value), + None => return None, + }; + + let value: T = match bincode::deserialize(&raw_value) { + Ok(data) => data, + Err(_) => return None, + }; + + let key = match std::str::from_utf8(&raw_key) { + Ok(key) => key.to_string(), + Err(_) => return None, + }; + + Some((key, value)) + } +} diff --git a/meilidb-data/src/database/index/mod.rs b/meilidb-data/src/database/index/mod.rs index 34c71db05..1f04fe934 100644 --- a/meilidb-data/src/database/index/mod.rs +++ b/meilidb-data/src/database/index/mod.rs @@ -18,6 +18,7 @@ use crate::ranked_map::RankedMap; use crate::serde::{Deserializer, DeserializerError}; pub use self::custom_settings_index::CustomSettingsIndex; +pub use self::common_index::CommonIndex; use self::docs_words_index::DocsWordsIndex; use self::documents_index::DocumentsIndex; use self::main_index::MainIndex; @@ -33,6 +34,7 @@ use crate::database::{ apply_synonyms_addition, apply_synonyms_deletion, }; +mod common_index; mod custom_settings_index; mod docs_words_index; mod documents_index; diff --git a/meilidb-data/src/database/mod.rs b/meilidb-data/src/database/mod.rs index c560bbe94..d5365124f 100644 --- a/meilidb-data/src/database/mod.rs +++ b/meilidb-data/src/database/mod.rs @@ -9,8 +9,10 @@ mod error; mod index; mod update; +use crate::CfTree; + pub use self::error::Error; -pub use self::index::{Index, CustomSettingsIndex}; +pub use self::index::{Index, CustomSettingsIndex, CommonIndex}; pub use self::update::DocumentsAddition; pub use self::update::DocumentsDeletion; @@ -23,6 +25,7 @@ use self::update::apply_synonyms_addition; use self::update::apply_synonyms_deletion; const INDEXES_KEY: &str = "indexes"; +const COMMON_KEY: &str = "common-index"; fn load_indexes(tree: &rocksdb::DB) -> Result, Error> { match tree.get(INDEXES_KEY)? { @@ -34,6 +37,7 @@ fn load_indexes(tree: &rocksdb::DB) -> Result, Error> { pub struct Database { cache: RwLock>, inner: Arc, + common: Arc, } impl Database { @@ -45,9 +49,10 @@ impl Database { let cfs = rocksdb::DB::list_cf(&options, &path).unwrap_or_default(); let inner = Arc::new(rocksdb::DB::open_cf(&options, path, cfs)?); - + let common_tree = CfTree::create(inner.clone(), COMMON_KEY.to_owned())?; + let common = Arc::new(CommonIndex(common_tree)); let indexes = load_indexes(&inner)?; - let database = Database { cache, inner }; + let database = Database { cache, inner, common }; for index in indexes { database.open_index(&index)?; @@ -112,4 +117,8 @@ impl Database { Ok(index) } + + pub fn common_index(&self) -> Arc { + self.common.clone() + } }