diff --git a/src/data/search.rs b/src/data/search.rs index 329efc3ea..33e48e4fd 100644 --- a/src/data/search.rs +++ b/src/data/search.rs @@ -1,7 +1,6 @@ use std::collections::HashSet; use std::mem; use std::time::Instant; -use std::ops::RangeBounds; use anyhow::{bail, Context}; use meilisearch_tokenizer::{Analyzer, AnalyzerConfig}; @@ -171,15 +170,14 @@ impl Data { &self, index: impl AsRef, offset: usize, - count: usize, + limit: usize, attributes_to_retrieve: Option<&[&str]>, ) -> anyhow::Result>> { let index = self.index_controller .index(&index)? .with_context(|| format!("Index {:?} doesn't exist", index.as_ref()))?; - let txn = index.read_txn()?; - let mut documents = Vec::new(); + let txn = index.read_txn()?; let fields_ids_map = index.fields_ids_map(&txn)?; @@ -194,7 +192,9 @@ impl Data { let iter = index.documents.range(&txn, &(..))? .skip(offset) - .take(count); + .take(limit); + + let mut documents = Vec::new(); for entry in iter { let (_id, obkv) = entry?; @@ -204,4 +204,42 @@ impl Data { Ok(documents) } + + pub fn retrieve_document( + &self, + index: impl AsRef, + document_id: impl AsRef, + attributes_to_retrieve: Option<&[&str]>, + ) -> anyhow::Result> { + let index = self.index_controller + .index(&index)? + .with_context(|| format!("Index {:?} doesn't exist", index.as_ref()))?; + let txn = index.read_txn()?; + + let fields_ids_map = index.fields_ids_map(&txn)?; + + let attributes_to_retrieve_ids = match attributes_to_retrieve { + Some(attrs) => attrs + .as_ref() + .iter() + .filter_map(|f| fields_ids_map.id(f)) + .collect::>(), + None => fields_ids_map.iter().map(|(id, _)| id).collect(), + }; + + let internal_id = index + .external_documents_ids(&txn)? + .get(document_id.as_ref().as_bytes()) + .with_context(|| format!("Document with id {} not found", document_id.as_ref()))?; + + let document = index.documents(&txn, std::iter::once(internal_id))? + .into_iter() + .next() + .map(|(_, d)| d); + + match document { + Some(document) => Ok(obkv_to_json(&attributes_to_retrieve_ids, &fields_ids_map, document)?), + None => bail!("Document with id {} not found", document_id.as_ref()), + } + } } diff --git a/src/index_controller/local_index_controller/update_store.rs b/src/index_controller/local_index_controller/update_store.rs index d4b796993..9f0c4ad7d 100644 --- a/src/index_controller/local_index_controller/update_store.rs +++ b/src/index_controller/local_index_controller/update_store.rs @@ -254,6 +254,7 @@ where /// Trying to abort an update that is currently being processed, an update /// that as already been processed or which doesn't actually exist, will /// return `None`. + #[allow(dead_code)] pub fn abort_update(&self, update_id: u64) -> heed::Result>> { let mut wtxn = self.env.write_txn()?; let key = BEU64::new(update_id); @@ -281,6 +282,7 @@ where /// Aborts all the pending updates, and not the one being currently processed. /// Returns the update metas and ids that were successfully aborted. + #[allow(dead_code)] pub fn abort_pendings(&self) -> heed::Result)>> { let mut wtxn = self.env.write_txn()?; let mut aborted_updates = Vec::new(); diff --git a/src/routes/document.rs b/src/routes/document.rs index 1114ddcb3..ac20cfff0 100644 --- a/src/routes/document.rs +++ b/src/routes/document.rs @@ -33,8 +33,8 @@ type Document = IndexMap; #[derive(Deserialize)] struct DocumentParam { - _index_uid: String, - _document_id: String, + index_uid: String, + document_id: String, } pub fn services(cfg: &mut web::ServiceConfig) { @@ -52,10 +52,21 @@ pub fn services(cfg: &mut web::ServiceConfig) { wrap = "Authentication::Public" )] async fn get_document( - _data: web::Data, - _path: web::Path, + data: web::Data, + path: web::Path, ) -> Result { - todo!() + let index = &path.index_uid; + let id = &path.document_id; + match data.retrieve_document(index, id, None) { + Ok(document) => { + let json = serde_json::to_string(&document).unwrap(); + Ok(HttpResponse::Ok().body(json)) + } + Err(e) => { + error!("{}", e); + unimplemented!() + } + } } #[delete(