From 53ad1fc068889bf4a789a53596928146f89000b7 Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 18 Sep 2019 16:58:51 +0200 Subject: [PATCH 01/10] chore: split tests into multiples files --- meilidb-data/tests/common.rs | 16 ++++++++ meilidb-data/tests/custom_settings_index.rs | 42 +++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 meilidb-data/tests/common.rs create mode 100644 meilidb-data/tests/custom_settings_index.rs diff --git a/meilidb-data/tests/common.rs b/meilidb-data/tests/common.rs new file mode 100644 index 000000000..dc6b22579 --- /dev/null +++ b/meilidb-data/tests/common.rs @@ -0,0 +1,16 @@ + +use meilidb_data::{Database}; +use meilidb_data::Index; +use meilidb_schema::{SchemaBuilder, DISPLAYED, INDEXED}; + +pub fn simple_index() -> Index { + let tmp_dir = tempfile::tempdir().unwrap(); + let database = Database::open(&tmp_dir).unwrap(); + + let mut builder = SchemaBuilder::with_identifier("objectId"); + builder.new_attribute("objectId", DISPLAYED | INDEXED); + builder.new_attribute("title", DISPLAYED | INDEXED); + let schema = builder.build(); + + database.create_index("hello", schema).unwrap() +} diff --git a/meilidb-data/tests/custom_settings_index.rs b/meilidb-data/tests/custom_settings_index.rs new file mode 100644 index 000000000..2f06a7e00 --- /dev/null +++ b/meilidb-data/tests/custom_settings_index.rs @@ -0,0 +1,42 @@ +mod common; +#[macro_use] extern crate maplit; + +use big_s::S; +use meilidb_data::{RankingOrdering}; + +#[test] +fn stop_words() { + let index = common::simple_index(); + let stop_words = hashset!{ S("le"), S("la"), S("les"), }; + index.custom_settings().set_stop_words(&stop_words).unwrap(); + let ret_stop_words = index.custom_settings().get_stop_words().unwrap().unwrap(); + assert_eq!(ret_stop_words, stop_words); +} + +#[test] +fn ranking_order() { + let index = common::simple_index(); + let ranking_order = vec![S("SumOfTypos"), S("NumberOfWords"), S("WordsProximity"), S("SumOfWordsAttribute"), S("SumOfWordsPosition"), S("Exact"), S("DocumentId")]; + index.custom_settings().set_ranking_order(&ranking_order).unwrap(); + let ret_ranking_orderer = index.custom_settings().get_ranking_order().unwrap().unwrap(); + assert_eq!(ret_ranking_orderer, ranking_order); +} + +#[test] +fn distinct_field() { + let index = common::simple_index(); + let distinct_field = S("title"); + index.custom_settings().set_distinct_field(&distinct_field).unwrap(); + let ret_distinct_field = index.custom_settings().get_distinct_field().unwrap().unwrap(); + assert_eq!(ret_distinct_field, distinct_field); +} + +#[test] +fn ranking_rules() { + let index = common::simple_index(); + let ranking_rules = hashmap!{ S("objectId") => RankingOrdering::Asc }; + index.custom_settings().set_ranking_rules(&ranking_rules).unwrap(); + let ret_ranking_rules = index.custom_settings().get_ranking_rules().unwrap().unwrap(); + assert_eq!(ret_ranking_rules, ranking_rules); +} + From 6ed97d1c19b37b951ae0287401b54ba8989966c5 Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 18 Sep 2019 17:04:31 +0200 Subject: [PATCH 02/10] chore: re-export UpdateType/DetailedDuration/UpdateStatus --- meilidb-data/src/database/mod.rs | 6 +++++- meilidb-data/src/lib.rs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/meilidb-data/src/database/mod.rs b/meilidb-data/src/database/mod.rs index b1391ac49..def7885f9 100644 --- a/meilidb-data/src/database/mod.rs +++ b/meilidb-data/src/database/mod.rs @@ -12,7 +12,11 @@ mod update; use crate::CfTree; pub use self::error::Error; -pub use self::index::{Index, CustomSettingsIndex, CommonIndex, RankingOrdering, StopWords, RankingOrder, DistinctField, RankingRules}; +pub use self::index::{ + Index, CustomSettingsIndex, CommonIndex, RankingOrdering, + StopWords, RankingOrder, DistinctField, RankingRules, + UpdateType, DetailedDuration, UpdateStatus +}; pub use self::update::DocumentsAddition; pub use self::update::DocumentsDeletion; diff --git a/meilidb-data/src/lib.rs b/meilidb-data/src/lib.rs index 168311755..32f6a22f4 100644 --- a/meilidb-data/src/lib.rs +++ b/meilidb-data/src/lib.rs @@ -7,7 +7,11 @@ mod ranked_map; mod serde; pub use self::cf_tree::{CfTree, CfIter}; -pub use self::database::{Database, Index, CustomSettingsIndex, RankingOrdering, StopWords, RankingOrder, DistinctField, RankingRules}; +pub use self::database::{ + Database, Index, CustomSettingsIndex, RankingOrdering, + StopWords, RankingOrder, DistinctField, RankingRules, + UpdateType, DetailedDuration, UpdateStatus +}; pub use self::number::Number; pub use self::ranked_map::RankedMap; pub use self::serde::{compute_document_id, extract_document_id, value_to_string}; From e3c413759f007539afa32fb1430da67b5eaf465f Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 18 Sep 2019 18:08:54 +0200 Subject: [PATCH 03/10] chore: implement deref on CommonIndex --- meilidb-data/src/database/index/common_index.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/meilidb-data/src/database/index/common_index.rs b/meilidb-data/src/database/index/common_index.rs index d102bb3bb..04fe39bd3 100644 --- a/meilidb-data/src/database/index/common_index.rs +++ b/meilidb-data/src/database/index/common_index.rs @@ -1,3 +1,4 @@ +use std::ops::Deref; use serde::de::DeserializeOwned; use serde::Serialize; use super::Error; @@ -6,6 +7,14 @@ use std::marker::PhantomData; #[derive(Clone)] pub struct CommonIndex(pub crate::CfTree); +impl Deref for CommonIndex { + type Target = crate::CfTree; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl CommonIndex { pub fn get(&self, key: K) -> Result, Error> where T: DeserializeOwned, From 522013425bb08898a636d669f9472b01dd546240 Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 18 Sep 2019 18:22:27 +0200 Subject: [PATCH 04/10] chore: export a getter for synonyms --- meilidb-data/src/database/index/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/meilidb-data/src/database/index/mod.rs b/meilidb-data/src/database/index/mod.rs index 9ee2e6804..2d6490d4c 100644 --- a/meilidb-data/src/database/index/mod.rs +++ b/meilidb-data/src/database/index/mod.rs @@ -316,6 +316,14 @@ impl Index { self.cache.load().schema.clone() } + pub fn synonyms_index(&self) -> SynonymsIndex { + self.synonyms_index.clone() + } + + pub fn synonyms_set(&self) -> Arc { + self.cache.load().synonyms.clone() + } + pub fn custom_settings(&self) -> CustomSettingsIndex { self.custom_settings_index.clone() } From 20f423268efdfba83aec414f6f6287b467b5c354 Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 18 Sep 2019 18:42:36 +0200 Subject: [PATCH 05/10] chore: re-export database::Error type --- meilidb-data/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meilidb-data/src/lib.rs b/meilidb-data/src/lib.rs index 32f6a22f4..6db3feec8 100644 --- a/meilidb-data/src/lib.rs +++ b/meilidb-data/src/lib.rs @@ -10,7 +10,7 @@ pub use self::cf_tree::{CfTree, CfIter}; pub use self::database::{ Database, Index, CustomSettingsIndex, RankingOrdering, StopWords, RankingOrder, DistinctField, RankingRules, - UpdateType, DetailedDuration, UpdateStatus + UpdateType, DetailedDuration, UpdateStatus, Error }; pub use self::number::Number; pub use self::ranked_map::RankedMap; From 941302a4becf140318c396e42644af8977eabb21 Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 19 Sep 2019 10:49:12 +0200 Subject: [PATCH 06/10] chore: export ranked map --- meilidb-data/src/database/index/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meilidb-data/src/database/index/mod.rs b/meilidb-data/src/database/index/mod.rs index 2d6490d4c..de822236b 100644 --- a/meilidb-data/src/database/index/mod.rs +++ b/meilidb-data/src/database/index/mod.rs @@ -316,6 +316,10 @@ impl Index { self.cache.load().schema.clone() } + pub fn ranked_map(&self) -> RankedMap { + self.cache.load().ranked_map.clone() + } + pub fn synonyms_index(&self) -> SynonymsIndex { self.synonyms_index.clone() } From 62e981c6b8510f23aa8ccf6fdfc75761d30054f6 Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 19 Sep 2019 11:01:43 +0200 Subject: [PATCH 07/10] chore: set public the main duration on update status --- meilidb-data/src/database/index/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meilidb-data/src/database/index/mod.rs b/meilidb-data/src/database/index/mod.rs index de822236b..afbcb325e 100644 --- a/meilidb-data/src/database/index/mod.rs +++ b/meilidb-data/src/database/index/mod.rs @@ -61,7 +61,7 @@ pub enum UpdateType { #[derive(Clone, Serialize, Deserialize)] pub struct DetailedDuration { - main: Duration, + pub main: Duration, } #[derive(Clone, Serialize, Deserialize)] From 120d209e6607044ac1e369cb1bbf6799c7d4d5ab Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 19 Sep 2019 11:51:10 +0200 Subject: [PATCH 08/10] chore: set public SchemaProps values --- meilidb-schema/src/lib.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/meilidb-schema/src/lib.rs b/meilidb-schema/src/lib.rs index 4655e2f07..5109b33e1 100644 --- a/meilidb-schema/src/lib.rs +++ b/meilidb-schema/src/lib.rs @@ -1,6 +1,4 @@ use std::collections::{HashMap, BTreeMap}; -use std::io::{Read, Write}; -use std::error::Error; use std::{fmt, u16}; use std::ops::BitOr; use std::sync::Arc; @@ -15,13 +13,13 @@ pub const RANKED: SchemaProps = SchemaProps { displayed: false, indexed: fals #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SchemaProps { #[serde(default)] - displayed: bool, + pub displayed: bool, #[serde(default)] - indexed: bool, + pub indexed: bool, #[serde(default)] - ranked: bool, + pub ranked: bool, } impl SchemaProps { From 7073b42afa85d4464e6dd132c9c2199fdfe6b850 Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 19 Sep 2019 17:29:22 +0200 Subject: [PATCH 09/10] feat: get update status Enqueued / Processed / Unknown --- meilidb-data/src/database/index/mod.rs | 42 ++++++++++++--------- meilidb-data/src/database/mod.rs | 2 +- meilidb-data/src/lib.rs | 3 +- meilidb-data/tests/common.rs | 1 - meilidb-data/tests/custom_settings_index.rs | 5 ++- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/meilidb-data/src/database/index/mod.rs b/meilidb-data/src/database/index/mod.rs index afbcb325e..0194b5d51 100644 --- a/meilidb-data/src/database/index/mod.rs +++ b/meilidb-data/src/database/index/mod.rs @@ -65,13 +65,20 @@ pub struct DetailedDuration { } #[derive(Clone, Serialize, Deserialize)] -pub struct UpdateStatus { +pub struct UpdateResult { pub update_id: u64, pub update_type: UpdateType, pub result: Result<(), String>, pub detailed_duration: DetailedDuration, } +#[derive(Clone, Serialize, Deserialize)] +pub enum UpdateStatus { + Enqueued, + Processed(UpdateResult), + Unknown, +} + fn spawn_update_system(index: Index, subscription: Receiver<()>) -> thread::JoinHandle<()> { thread::spawn(move || { let mut subscription = subscription.into_iter(); @@ -115,7 +122,7 @@ fn spawn_update_system(index: Index, subscription: Receiver<()>) -> thread::Join }; let detailed_duration = DetailedDuration { main: duration }; - let status = UpdateStatus { + let status = UpdateResult { update_id, update_type, result: result.map_err(|e| e.to_string()), @@ -180,7 +187,7 @@ pub struct Index { updates_id: Arc, updates_index: crate::CfTree, updates_results_index: crate::CfTree, - update_callback: Arc>>, + update_callback: Arc>>, } pub(crate) struct Cache { @@ -266,7 +273,7 @@ impl Index { } pub fn set_update_callback(&self, callback: F) - where F: Fn(UpdateStatus) + Send + Sync + 'static + where F: Fn(UpdateResult) + Send + Sync + 'static { self.update_callback.store(Some(Arc::new(Box::new(callback)))); } @@ -355,36 +362,35 @@ impl Index { pub fn update_status( &self, update_id: u64, - ) -> Result, Error> + ) -> Result { let update_id = update_id.to_be_bytes(); match self.updates_results_index.get(update_id)? { Some(value) => { let value = bincode::deserialize(&value)?; - Ok(Some(value)) + Ok(UpdateStatus::Processed(value)) }, - None => Ok(None), + None => { + match self.updates_index.get(update_id)? { + Some(_) => Ok(UpdateStatus::Enqueued), + None => Ok(UpdateStatus::Unknown), + } + } } } pub fn update_status_blocking( &self, update_id: u64, - ) -> Result + ) -> Result { - // if we find the update result return it now - if let Some(result) = self.update_status(update_id)? { - return Ok(result) - } - loop { - if self.updates_results_index.get(&update_id.to_be_bytes())?.is_some() { break } + if let Some(value) = self.updates_results_index.get(&update_id.to_be_bytes())? { + let value = bincode::deserialize(&value)?; + return Ok(value) + } std::thread::sleep(Duration::from_millis(300)); } - - // the thread has been unblocked, it means that the update result - // has been inserted in the tree, retrieve it - Ok(self.update_status(update_id)?.unwrap()) } pub fn documents_ids(&self) -> Result { diff --git a/meilidb-data/src/database/mod.rs b/meilidb-data/src/database/mod.rs index def7885f9..c4ff406a5 100644 --- a/meilidb-data/src/database/mod.rs +++ b/meilidb-data/src/database/mod.rs @@ -15,7 +15,7 @@ pub use self::error::Error; pub use self::index::{ Index, CustomSettingsIndex, CommonIndex, RankingOrdering, StopWords, RankingOrder, DistinctField, RankingRules, - UpdateType, DetailedDuration, UpdateStatus + UpdateType, DetailedDuration, UpdateResult, UpdateStatus }; pub use self::update::DocumentsAddition; diff --git a/meilidb-data/src/lib.rs b/meilidb-data/src/lib.rs index 6db3feec8..8d313c855 100644 --- a/meilidb-data/src/lib.rs +++ b/meilidb-data/src/lib.rs @@ -10,7 +10,8 @@ pub use self::cf_tree::{CfTree, CfIter}; pub use self::database::{ Database, Index, CustomSettingsIndex, RankingOrdering, StopWords, RankingOrder, DistinctField, RankingRules, - UpdateType, DetailedDuration, UpdateStatus, Error + UpdateType, DetailedDuration, UpdateResult, UpdateStatus, + Error, }; pub use self::number::Number; pub use self::ranked_map::RankedMap; diff --git a/meilidb-data/tests/common.rs b/meilidb-data/tests/common.rs index dc6b22579..8d0aadda7 100644 --- a/meilidb-data/tests/common.rs +++ b/meilidb-data/tests/common.rs @@ -1,4 +1,3 @@ - use meilidb_data::{Database}; use meilidb_data::Index; use meilidb_schema::{SchemaBuilder, DISPLAYED, INDEXED}; diff --git a/meilidb-data/tests/custom_settings_index.rs b/meilidb-data/tests/custom_settings_index.rs index 2f06a7e00..9363be9d8 100644 --- a/meilidb-data/tests/custom_settings_index.rs +++ b/meilidb-data/tests/custom_settings_index.rs @@ -1,8 +1,9 @@ -mod common; #[macro_use] extern crate maplit; +mod common; + use big_s::S; -use meilidb_data::{RankingOrdering}; +use meilidb_data::RankingOrdering; #[test] fn stop_words() { From d7d1b6ff029da3d71fd66b0df5c99fae8878cfad Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 19 Sep 2019 17:50:11 +0200 Subject: [PATCH 10/10] chore: reformat tests --- meilidb-data/tests/database.rs | 67 ++++++++++ meilidb-data/tests/index.rs | 99 +++++++++++++++ meilidb-data/tests/updates.rs | 215 --------------------------------- 3 files changed, 166 insertions(+), 215 deletions(-) create mode 100644 meilidb-data/tests/database.rs create mode 100644 meilidb-data/tests/index.rs delete mode 100644 meilidb-data/tests/updates.rs diff --git a/meilidb-data/tests/database.rs b/meilidb-data/tests/database.rs new file mode 100644 index 000000000..b716b2ea7 --- /dev/null +++ b/meilidb-data/tests/database.rs @@ -0,0 +1,67 @@ +#[macro_use] extern crate maplit; + +mod common; + +use std::sync::atomic::{AtomicBool, Ordering::Relaxed}; +use std::sync::Arc; + +use big_s::S; +use serde_json::json; + +#[test] +fn database_stats() { + let index = common::simple_index(); + let as_been_updated = Arc::new(AtomicBool::new(false)); + + let as_been_updated_clone = as_been_updated.clone(); + index.set_update_callback(move |_| as_been_updated_clone.store(true, Relaxed)); + + let doc1 = json!({ "objectId": 123, "title": "hello" }); + + let mut addition = index.documents_addition(); + addition.update_document(&doc1); + let update_id = addition.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(as_been_updated.swap(false, Relaxed)); + assert!(status.result.is_ok()); + let stats = index.stats().unwrap(); + let repartition = hashmap!{ + S("objectId") => 1u64, + S("title") => 1u64, + }; + assert_eq!(stats.number_of_documents, 1); + assert_eq!(stats.documents_fields_repartition, repartition); + + let doc2 = json!({ "objectId": 456, "title": "world" }); + + let mut addition = index.documents_addition(); + addition.update_document(&doc2); + let update_id = addition.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(as_been_updated.swap(false, Relaxed)); + assert!(status.result.is_ok()); + let stats = index.stats().unwrap(); + let repartition = hashmap!{ + S("objectId") => 2u64, + S("title") => 2u64, + }; + assert_eq!(stats.number_of_documents, 2); + assert_eq!(stats.documents_fields_repartition, repartition); + + + let doc3 = json!({ "objectId": 789 }); + + let mut addition = index.documents_addition(); + addition.update_document(&doc3); + let update_id = addition.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(as_been_updated.swap(false, Relaxed)); + assert!(status.result.is_ok()); + let stats = index.stats().unwrap(); + let repartition = hashmap!{ + S("objectId") => 3u64, + S("title") => 2u64, + }; + assert_eq!(stats.number_of_documents, 3); + assert_eq!(stats.documents_fields_repartition, repartition); +} diff --git a/meilidb-data/tests/index.rs b/meilidb-data/tests/index.rs new file mode 100644 index 000000000..4d7a7658b --- /dev/null +++ b/meilidb-data/tests/index.rs @@ -0,0 +1,99 @@ +mod common; + +use std::sync::atomic::{AtomicBool, Ordering::Relaxed}; +use std::sync::Arc; + +use serde_json::json; + +#[test] +fn insert_delete_document() { + let index = common::simple_index(); + let as_been_updated = Arc::new(AtomicBool::new(false)); + + let as_been_updated_clone = as_been_updated.clone(); + index.set_update_callback(move |_| as_been_updated_clone.store(true, Relaxed)); + + let doc1 = json!({ "objectId": 123, "title": "hello" }); + + let mut addition = index.documents_addition(); + addition.update_document(&doc1); + let update_id = addition.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(as_been_updated.swap(false, Relaxed)); + assert!(status.result.is_ok()); + assert_eq!(index.number_of_documents(), 1); + + let docs = index.query_builder().query("hello", 0..10).unwrap(); + assert_eq!(docs.len(), 1); + assert_eq!(index.document(None, docs[0].id).unwrap().as_ref(), Some(&doc1)); + + let mut deletion = index.documents_deletion(); + deletion.delete_document(&doc1).unwrap(); + let update_id = deletion.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(as_been_updated.swap(false, Relaxed)); + assert!(status.result.is_ok()); + assert_eq!(index.number_of_documents(), 0); + + let docs = index.query_builder().query("hello", 0..10).unwrap(); + assert_eq!(docs.len(), 0); +} + +#[test] +fn replace_document() { + let index = common::simple_index(); + let as_been_updated = Arc::new(AtomicBool::new(false)); + + let as_been_updated_clone = as_been_updated.clone(); + index.set_update_callback(move |_| as_been_updated_clone.store(true, Relaxed)); + + let doc1 = json!({ "objectId": 123, "title": "hello" }); + let doc2 = json!({ "objectId": 123, "title": "coucou" }); + + let mut addition = index.documents_addition(); + addition.update_document(&doc1); + let update_id = addition.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(as_been_updated.swap(false, Relaxed)); + assert!(status.result.is_ok()); + assert_eq!(index.number_of_documents(), 1); + + let docs = index.query_builder().query("hello", 0..10).unwrap(); + assert_eq!(docs.len(), 1); + assert_eq!(index.document(None, docs[0].id).unwrap().as_ref(), Some(&doc1)); + + let mut addition = index.documents_addition(); + addition.update_document(&doc2); + let update_id = addition.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(as_been_updated.swap(false, Relaxed)); + assert!(status.result.is_ok()); + assert_eq!(index.number_of_documents(), 1); + + let docs = index.query_builder().query("hello", 0..10).unwrap(); + assert_eq!(docs.len(), 0); + + let docs = index.query_builder().query("coucou", 0..10).unwrap(); + assert_eq!(docs.len(), 1); + assert_eq!(index.document(None, docs[0].id).unwrap().as_ref(), Some(&doc2)); +} + +#[test] +fn documents_ids() { + let index = common::simple_index(); + + let doc1 = json!({ "objectId": 123, "title": "hello" }); + let doc2 = json!({ "objectId": 456, "title": "world" }); + let doc3 = json!({ "objectId": 789 }); + + let mut addition = index.documents_addition(); + addition.update_document(&doc1); + addition.update_document(&doc2); + addition.update_document(&doc3); + let update_id = addition.finalize().unwrap(); + let status = index.update_status_blocking(update_id).unwrap(); + assert!(status.result.is_ok()); + + let documents_ids_count = index.documents_ids().unwrap().count(); + assert_eq!(documents_ids_count, 3); +} diff --git a/meilidb-data/tests/updates.rs b/meilidb-data/tests/updates.rs deleted file mode 100644 index d106769cb..000000000 --- a/meilidb-data/tests/updates.rs +++ /dev/null @@ -1,215 +0,0 @@ -#[macro_use] extern crate maplit; - -use std::sync::atomic::{AtomicBool, Ordering::Relaxed}; -use std::sync::Arc; - -use big_s::S; -use serde_json::json; -use meilidb_data::{Database, RankingOrdering}; -use meilidb_schema::{Schema, SchemaBuilder, DISPLAYED, INDEXED}; - -fn simple_schema() -> Schema { - let mut builder = SchemaBuilder::with_identifier("objectId"); - builder.new_attribute("objectId", DISPLAYED | INDEXED); - builder.new_attribute("title", DISPLAYED | INDEXED); - builder.build() -} - -#[test] -fn insert_delete_document() { - let tmp_dir = tempfile::tempdir().unwrap(); - let database = Database::open(&tmp_dir).unwrap(); - - let as_been_updated = Arc::new(AtomicBool::new(false)); - - let schema = simple_schema(); - let index = database.create_index("hello", schema).unwrap(); - - let as_been_updated_clone = as_been_updated.clone(); - index.set_update_callback(move |_| as_been_updated_clone.store(true, Relaxed)); - - let doc1 = json!({ "objectId": 123, "title": "hello" }); - - let mut addition = index.documents_addition(); - addition.update_document(&doc1); - let update_id = addition.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(as_been_updated.swap(false, Relaxed)); - assert!(status.result.is_ok()); - assert_eq!(index.number_of_documents(), 1); - - let docs = index.query_builder().query("hello", 0..10).unwrap(); - assert_eq!(docs.len(), 1); - assert_eq!(index.document(None, docs[0].id).unwrap().as_ref(), Some(&doc1)); - - let mut deletion = index.documents_deletion(); - deletion.delete_document(&doc1).unwrap(); - let update_id = deletion.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(as_been_updated.swap(false, Relaxed)); - assert!(status.result.is_ok()); - assert_eq!(index.number_of_documents(), 0); - - let docs = index.query_builder().query("hello", 0..10).unwrap(); - assert_eq!(docs.len(), 0); -} - -#[test] -fn replace_document() { - let tmp_dir = tempfile::tempdir().unwrap(); - let database = Database::open(&tmp_dir).unwrap(); - - let as_been_updated = Arc::new(AtomicBool::new(false)); - - let schema = simple_schema(); - let index = database.create_index("hello", schema).unwrap(); - - let as_been_updated_clone = as_been_updated.clone(); - index.set_update_callback(move |_| as_been_updated_clone.store(true, Relaxed)); - - let doc1 = json!({ "objectId": 123, "title": "hello" }); - let doc2 = json!({ "objectId": 123, "title": "coucou" }); - - let mut addition = index.documents_addition(); - addition.update_document(&doc1); - let update_id = addition.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(as_been_updated.swap(false, Relaxed)); - assert!(status.result.is_ok()); - assert_eq!(index.number_of_documents(), 1); - - let docs = index.query_builder().query("hello", 0..10).unwrap(); - assert_eq!(docs.len(), 1); - assert_eq!(index.document(None, docs[0].id).unwrap().as_ref(), Some(&doc1)); - - let mut addition = index.documents_addition(); - addition.update_document(&doc2); - let update_id = addition.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(as_been_updated.swap(false, Relaxed)); - assert!(status.result.is_ok()); - assert_eq!(index.number_of_documents(), 1); - - let docs = index.query_builder().query("hello", 0..10).unwrap(); - assert_eq!(docs.len(), 0); - - let docs = index.query_builder().query("coucou", 0..10).unwrap(); - assert_eq!(docs.len(), 1); - assert_eq!(index.document(None, docs[0].id).unwrap().as_ref(), Some(&doc2)); -} - -#[test] -fn database_stats() { - let tmp_dir = tempfile::tempdir().unwrap(); - let database = Database::open(&tmp_dir).unwrap(); - - let as_been_updated = Arc::new(AtomicBool::new(false)); - - let schema = simple_schema(); - let index = database.create_index("hello", schema).unwrap(); - - let as_been_updated_clone = as_been_updated.clone(); - index.set_update_callback(move |_| as_been_updated_clone.store(true, Relaxed)); - - let doc1 = json!({ "objectId": 123, "title": "hello" }); - - let mut addition = index.documents_addition(); - addition.update_document(&doc1); - let update_id = addition.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(as_been_updated.swap(false, Relaxed)); - assert!(status.result.is_ok()); - let stats = index.stats().unwrap(); - let repartition = hashmap!{ - S("objectId") => 1u64, - S("title") => 1u64, - }; - assert_eq!(stats.number_of_documents, 1); - assert_eq!(stats.documents_fields_repartition, repartition); - - let doc2 = json!({ "objectId": 456, "title": "world" }); - - let mut addition = index.documents_addition(); - addition.update_document(&doc2); - let update_id = addition.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(as_been_updated.swap(false, Relaxed)); - assert!(status.result.is_ok()); - let stats = index.stats().unwrap(); - let repartition = hashmap!{ - S("objectId") => 2u64, - S("title") => 2u64, - }; - assert_eq!(stats.number_of_documents, 2); - assert_eq!(stats.documents_fields_repartition, repartition); - - - let doc3 = json!({ "objectId": 789 }); - - let mut addition = index.documents_addition(); - addition.update_document(&doc3); - let update_id = addition.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(as_been_updated.swap(false, Relaxed)); - assert!(status.result.is_ok()); - let stats = index.stats().unwrap(); - let repartition = hashmap!{ - S("objectId") => 3u64, - S("title") => 2u64, - }; - assert_eq!(stats.number_of_documents, 3); - assert_eq!(stats.documents_fields_repartition, repartition); -} - -#[test] -fn custom_settings() { - let tmp_dir = tempfile::tempdir().unwrap(); - let database = Database::open(&tmp_dir).unwrap(); - - let schema = simple_schema(); - let index = database.create_index("hello", schema).unwrap(); - - let stop_words = hashset!{ S("le"), S("la"), S("les"), }; - let ranking_order = vec![S("SumOfTypos"), S("NumberOfWords"), S("WordsProximity"), S("SumOfWordsAttribute"), S("SumOfWordsPosition"), S("Exact"), S("DocumentId")]; - let distinct_field = S("title"); - let ranking_rules = hashmap!{ S("objectId") => RankingOrdering::Asc }; - - index.custom_settings().set_stop_words(&stop_words).unwrap(); - index.custom_settings().set_ranking_order(&ranking_order).unwrap(); - index.custom_settings().set_distinct_field(&distinct_field).unwrap(); - index.custom_settings().set_ranking_rules(&ranking_rules).unwrap(); - - let ret_stop_words = index.custom_settings().get_stop_words().unwrap().unwrap(); - let ret_ranking_orderer = index.custom_settings().get_ranking_order().unwrap().unwrap(); - let ret_distinct_field = index.custom_settings().get_distinct_field().unwrap().unwrap(); - let ret_ranking_rules = index.custom_settings().get_ranking_rules().unwrap().unwrap(); - - assert_eq!(ret_stop_words, stop_words); - assert_eq!(ret_ranking_orderer, ranking_order); - assert_eq!(ret_distinct_field, distinct_field); - assert_eq!(ret_ranking_rules, ranking_rules); -} - -#[test] -fn documents_ids() { - let tmp_dir = tempfile::tempdir().unwrap(); - let database = Database::open(&tmp_dir).unwrap(); - - let schema = simple_schema(); - let index = database.create_index("hello", schema).unwrap(); - - let doc1 = json!({ "objectId": 123, "title": "hello" }); - let doc2 = json!({ "objectId": 456, "title": "world" }); - let doc3 = json!({ "objectId": 789 }); - - let mut addition = index.documents_addition(); - addition.update_document(&doc1); - addition.update_document(&doc2); - addition.update_document(&doc3); - let update_id = addition.finalize().unwrap(); - let status = index.update_status_blocking(update_id).unwrap(); - assert!(status.result.is_ok()); - - let documents_ids_count = index.documents_ids().unwrap().count(); - assert_eq!(documents_ids_count, 3); -}