diff --git a/meilisearch-http/src/routes/indexes/documents.rs b/meilisearch-http/src/routes/indexes/documents.rs index 821b962ea..ee86e12ad 100644 --- a/meilisearch-http/src/routes/indexes/documents.rs +++ b/meilisearch-http/src/routes/indexes/documents.rs @@ -7,7 +7,7 @@ use meilisearch_lib::MeiliSearch; use meilisearch_lib::index_controller::{DocumentAdditionFormat, Update}; use milli::update::IndexDocumentsMethod; use serde::Deserialize; -//use serde_json::Value; +use serde_json::Value; use tokio::sync::mpsc; use crate::error::ResponseError; @@ -76,14 +76,14 @@ pub fn configure(cfg: &mut web::ServiceConfig) { .route(web::get().to(get_all_documents)) .route(web::post().guard(guard_json).to(add_documents)) .route(web::put().guard(guard_json).to(update_documents)) - //.route(web::delete().to(clear_all_documents)), + .route(web::delete().to(clear_all_documents)), ) // this route needs to be before the /documents/{document_id} to match properly - //.service(web::resource("/delete-batch").route(web::post().to(delete_documents))) + .service(web::resource("/delete-batch").route(web::post().to(delete_documents))) .service( web::resource("/{document_id}") .route(web::get().to(get_document)) - //.route(web::delete().to(delete_document)), + .route(web::delete().to(delete_document)), ); } @@ -100,16 +100,16 @@ pub async fn get_document( Ok(HttpResponse::Ok().json(document)) } -//pub async fn delete_document( - //data: GuardedData, - //path: web::Path, -//) -> Result { - //let update_status = data - //.delete_documents(path.index_uid.clone(), vec![path.document_id.clone()]) - //.await?; - //debug!("returns: {:?}", update_status); - //Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) -//} +pub async fn delete_document( + meilisearch: GuardedData, + path: web::Path, +) -> Result { + let DocumentParam { document_id, index_uid } = path.into_inner(); + let update = Update::DeleteDocuments(vec![document_id]); + let update_status = meilisearch.register_update(index_uid, update).await?; + debug!("returns: {:?}", update_status); + Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) +} #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -200,31 +200,33 @@ pub async fn update_documents( Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) } -//pub async fn delete_documents( - //data: GuardedData, - //path: web::Path, - //body: web::Json>, -//) -> Result { - //debug!("called with params: {:?}", body); - //let ids = body - //.iter() - //.map(|v| { - //v.as_str() - //.map(String::from) - //.unwrap_or_else(|| v.to_string()) - //}) - //.collect(); +pub async fn delete_documents( + meilisearch: GuardedData, + path: web::Path, + body: web::Json>, +) -> Result { + debug!("called with params: {:?}", body); + let ids = body + .iter() + .map(|v| { + v.as_str() + .map(String::from) + .unwrap_or_else(|| v.to_string()) + }) + .collect(); - //let update_status = data.delete_documents(path.index_uid.clone(), ids).await?; - //debug!("returns: {:?}", update_status); - //Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) -//} + let update = Update::DeleteDocuments(ids); + let update_status = meilisearch.register_update(path.into_inner().index_uid, update).await?; + debug!("returns: {:?}", update_status); + Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) +} -//pub async fn clear_all_documents( - //data: GuardedData, - //path: web::Path, -//) -> Result { - //let update_status = data.clear_documents(path.index_uid.clone()).await?; - //debug!("returns: {:?}", update_status); - //Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) -//} +pub async fn clear_all_documents( + meilisearch: GuardedData, + path: web::Path, +) -> Result { + let update = Update::ClearDocuments; + let update_status = meilisearch.register_update(path.into_inner().index_uid, update).await?; + debug!("returns: {:?}", update_status); + Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) +} diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index b30fce164..9d99a7d0c 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -72,10 +72,10 @@ impl From<&UpdateStatus> for UpdateType { RegisterUpdate::Settings(settings) => UpdateType::Settings { settings: settings.clone(), }, - //UpdateMeta::ClearDocuments => UpdateType::ClearAll, - //UpdateMeta::DeleteDocuments { ids } => UpdateType::DocumentsDeletion { - //number: Some(ids.len()), - //}, + RegisterUpdate::ClearDocuments => UpdateType::ClearAll, + RegisterUpdate::DeleteDocuments(ids) => UpdateType::DocumentsDeletion { + number: Some(ids.len()), + }, } } } diff --git a/meilisearch-lib/src/index/updates.rs b/meilisearch-lib/src/index/updates.rs index fca925031..28d2734f0 100644 --- a/meilisearch-lib/src/index/updates.rs +++ b/meilisearch-lib/src/index/updates.rs @@ -177,6 +177,22 @@ impl Index { let settings = settings.clone().check(); self.update_settings(&mut txn, &settings, update_builder) }, + RegisterUpdate::ClearDocuments => { + let builder = update_builder.clear_documents(&mut txn, self); + let _count = builder.execute()?; + Ok(UpdateResult::Other) + }, + RegisterUpdate::DeleteDocuments(ids) => { + let mut builder = update_builder.delete_documents(&mut txn, self)?; + + // We ignore unexisting document ids + ids.iter().for_each(|id| { + builder.delete_external_id(id); + }); + + let deleted = builder.execute()?; + Ok(UpdateResult::DocumentDeletion { deleted }) + } }; txn.commit()?; result @@ -241,18 +257,6 @@ impl Index { Ok(UpdateResult::DocumentsAddition(addition)) } - //pub fn clear_documents(&self, update_builder: UpdateBuilder) -> Result { - //// We must use the write transaction of the update here. - //let mut wtxn = self.write_txn()?; - //let builder = update_builder.clear_documents(&mut wtxn, self); - - //let _count = builder.execute()?; - - //wtxn.commit() - //.and(Ok(UpdateResult::Other)) - //.map_err(Into::into) - //} - fn update_settings<'a, 'b>( &'a self, txn: &mut heed::RwTxn<'a, 'b>, @@ -322,25 +326,6 @@ impl Index { Ok(UpdateResult::Other) } - - //pub fn delete_documents( - //&self, - //document_ids: &[String], - //update_builder: UpdateBuilder, - //) -> Result { - //let mut txn = self.write_txn()?; - //let mut builder = update_builder.delete_documents(&mut txn, self)?; - - //// We ignore unexisting document ids - //document_ids.iter().for_each(|id| { - //builder.delete_external_id(id); - //}); - - //let deleted = builder.execute()?; - //txn.commit() - //.and(Ok(UpdateResult::DocumentDeletion { deleted })) - //.map_err(Into::into) - //} } #[cfg(test)] diff --git a/meilisearch-lib/src/index_controller/mod.rs b/meilisearch-lib/src/index_controller/mod.rs index f9ff4fbbe..3c53ab9eb 100644 --- a/meilisearch-lib/src/index_controller/mod.rs +++ b/meilisearch-lib/src/index_controller/mod.rs @@ -95,6 +95,8 @@ pub struct Stats { #[derive(derivative::Derivative)] #[derivative(Debug)] pub enum Update { + DeleteDocuments(Vec), + ClearDocuments, Settings(Settings), DocumentAddition { #[derivative(Debug="ignore")] diff --git a/meilisearch-lib/src/index_controller/updates/mod.rs b/meilisearch-lib/src/index_controller/updates/mod.rs index 30b6d98f6..2027f5245 100644 --- a/meilisearch-lib/src/index_controller/updates/mod.rs +++ b/meilisearch-lib/src/index_controller/updates/mod.rs @@ -49,12 +49,14 @@ pub fn create_update_handler( #[derive(Debug, Clone, Serialize, Deserialize)] pub enum RegisterUpdate { + DeleteDocuments(Vec), DocumentAddition { primary_key: Option, method: IndexDocumentsMethod, content_uuid: Uuid, }, Settings(Settings), + ClearDocuments, } /// A wrapper type to implement read on a `Stream>`. @@ -210,6 +212,8 @@ impl UpdateLoop { } } Update::Settings(settings) => RegisterUpdate::Settings(settings), + Update::ClearDocuments => RegisterUpdate::ClearDocuments, + Update::DeleteDocuments(ids) => RegisterUpdate::DeleteDocuments(ids), }; let store = self.store.clone();