diff --git a/Cargo.lock b/Cargo.lock index 1f34a388e..f717be694 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1588,7 +1588,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "meilisearch-error" -version = "0.17.0" +version = "0.15.0" dependencies = [ "actix-http", ] diff --git a/src/data/mod.rs b/src/data/mod.rs index a699c9d20..9d64052af 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -3,6 +3,7 @@ mod updates; pub use search::{SearchQuery, SearchResult}; +use std::collections::HashMap; use std::fs::create_dir_all; use std::ops::Deref; use std::sync::Arc; @@ -10,7 +11,7 @@ use std::sync::Arc; use milli::Index; use sha2::Digest; -use crate::option::Opt; +use crate::{option::Opt, updates::Settings}; use crate::updates::UpdateQueue; #[derive(Clone)] @@ -82,6 +83,39 @@ impl Data { Ok(Data { inner }) } + pub fn settings>(&self, _index: S) -> anyhow::Result { + let txn = self.indexes.env.read_txn()?; + let fields_map = self.indexes.fields_ids_map(&txn)?; + println!("fields_map: {:?}", fields_map); + + let displayed_attributes = self.indexes + .displayed_fields(&txn)? + .map(|fields| {println!("{:?}", fields); fields.iter().filter_map(|f| fields_map.name(*f).map(String::from)).collect()}) + .unwrap_or_else(|| vec!["*".to_string()]); + + let searchable_attributes = self.indexes + .searchable_fields(&txn)? + .map(|fields| fields + .iter() + .filter_map(|f| fields_map.name(*f).map(String::from)) + .collect()) + .unwrap_or_else(|| vec!["*".to_string()]); + + let faceted_attributes = self.indexes + .faceted_fields(&txn)? + .iter() + .filter_map(|(f, t)| Some((fields_map.name(*f)?.to_string(), t.to_string()))) + .collect::>() + .into(); + + Ok(Settings { + displayed_attributes: Some(Some(displayed_attributes)), + searchable_attributes: Some(Some(searchable_attributes)), + faceted_attributes: Some(faceted_attributes), + criteria: None, + }) + } + #[inline] pub fn http_payload_size_limit(&self) -> usize { self.options.http_payload_size_limit.get_bytes() as usize diff --git a/src/data/updates.rs b/src/data/updates.rs index bb96c53c6..0654f6fd3 100644 --- a/src/data/updates.rs +++ b/src/data/updates.rs @@ -7,7 +7,7 @@ use milli::update::{IndexDocumentsMethod, UpdateFormat}; use milli::update_store::UpdateStatus; use super::Data; -use crate::updates::{UpdateMeta, UpdateResult}; +use crate::updates::{UpdateMeta, UpdateResult, UpdateStatusResponse, Settings}; impl Data { pub async fn add_documents( @@ -16,7 +16,7 @@ impl Data { method: IndexDocumentsMethod, format: UpdateFormat, mut stream: impl futures::Stream> + Unpin, - ) -> anyhow::Result> + ) -> anyhow::Result where B: Deref, E: std::error::Error + Send + Sync + 'static, @@ -45,6 +45,16 @@ impl Data { Ok(update.into()) } + pub async fn update_settings>( + &self, + _index: S, + settings: Settings + ) -> anyhow::Result { + let meta = UpdateMeta::Settings(settings); + let queue = self.update_queue.clone(); + let update = tokio::task::spawn_blocking(move || queue.register_update(meta, &[])).await??; + Ok(update.into()) + } #[inline] pub fn get_update_status(&self, _index: &str, uid: u64) -> anyhow::Result>> { diff --git a/src/lib.rs b/src/lib.rs index 2c625588d..e0ae9aedb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ pub fn create_app( .configure(routes::document::services) .configure(routes::index::services) .configure(routes::search::services) - .configure(routes::setting::services) + .configure(routes::settings::services) .configure(routes::stop_words::services) .configure(routes::synonym::services) .configure(routes::health::services) diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 4b0813067..e1345fa08 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -6,7 +6,7 @@ pub mod health; pub mod index; pub mod key; pub mod search; -pub mod setting; +pub mod settings; pub mod stats; pub mod stop_words; pub mod synonym; diff --git a/src/routes/setting.rs b/src/routes/setting.rs deleted file mode 100644 index a405de45a..000000000 --- a/src/routes/setting.rs +++ /dev/null @@ -1,226 +0,0 @@ -use std::collections::BTreeSet; - -use actix_web::{delete, get, post}; -use actix_web::{web, HttpResponse}; - -use crate::Data; -use crate::error::ResponseError; -use crate::helpers::Authentication; -use crate::updates::Settings; - -pub fn services(cfg: &mut web::ServiceConfig) { - cfg.service(update_all) - .service(get_all) - .service(delete_all) - .service(get_rules) - .service(update_rules) - .service(delete_rules) - .service(get_distinct) - .service(update_distinct) - .service(delete_distinct) - .service(get_searchable) - .service(update_searchable) - .service(delete_searchable) - .service(get_displayed) - .service(update_displayed) - .service(delete_displayed) - .service(get_attributes_for_faceting) - .service(delete_attributes_for_faceting) - .service(update_attributes_for_faceting); -} - - -#[post("/indexes/{index_uid}/settings", wrap = "Authentication::Private")] -async fn update_all( - _data: web::Data, - _path: web::Path, - _body: web::Json, -) -> Result { - todo!() -} - -#[get("/indexes/{index_uid}/settings", wrap = "Authentication::Private")] -async fn get_all( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[delete("/indexes/{index_uid}/settings", wrap = "Authentication::Private")] -async fn delete_all( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[get( - "/indexes/{index_uid}/settings/ranking-rules", - wrap = "Authentication::Private" -)] -async fn get_rules( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[post( - "/indexes/{index_uid}/settings/ranking-rules", - wrap = "Authentication::Private" -)] -async fn update_rules( - _data: web::Data, - _path: web::Path, - _body: web::Json>>, -) -> Result { - todo!() -} - -#[delete( - "/indexes/{index_uid}/settings/ranking-rules", - wrap = "Authentication::Private" -)] -async fn delete_rules( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[get( - "/indexes/{index_uid}/settings/distinct-attribute", - wrap = "Authentication::Private" -)] -async fn get_distinct( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[post( - "/indexes/{index_uid}/settings/distinct-attribute", - wrap = "Authentication::Private" -)] -async fn update_distinct( - _data: web::Data, - _path: web::Path, - _body: web::Json>, -) -> Result { - todo!() -} - -#[delete( - "/indexes/{index_uid}/settings/distinct-attribute", - wrap = "Authentication::Private" -)] -async fn delete_distinct( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[get( - "/indexes/{index_uid}/settings/searchable-attributes", - wrap = "Authentication::Private" -)] -async fn get_searchable( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[post( - "/indexes/{index_uid}/settings/searchable-attributes", - wrap = "Authentication::Private" -)] -async fn update_searchable( - _data: web::Data, - _path: web::Path, - _body: web::Json>>, -) -> Result { - todo!() -} - -#[delete( - "/indexes/{index_uid}/settings/searchable-attributes", - wrap = "Authentication::Private" -)] -async fn delete_searchable( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[get( - "/indexes/{index_uid}/settings/displayed-attributes", - wrap = "Authentication::Private" -)] -async fn get_displayed( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[post( - "/indexes/{index_uid}/settings/displayed-attributes", - wrap = "Authentication::Private" -)] -async fn update_displayed( - _data: web::Data, - _path: web::Path, - _body: web::Json>>, -) -> Result { - todo!() -} - -#[delete( - "/indexes/{index_uid}/settings/displayed-attributes", - wrap = "Authentication::Private" -)] -async fn delete_displayed( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[get( - "/indexes/{index_uid}/settings/attributes-for-faceting", - wrap = "Authentication::Private" -)] -async fn get_attributes_for_faceting( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} - -#[post( - "/indexes/{index_uid}/settings/attributes-for-faceting", - wrap = "Authentication::Private" -)] -async fn update_attributes_for_faceting( - _data: web::Data, - _path: web::Path, - _body: web::Json>>, -) -> Result { - todo!() -} - -#[delete( - "/indexes/{index_uid}/settings/attributes-for-faceting", - wrap = "Authentication::Private" -)] -async fn delete_attributes_for_faceting( - _data: web::Data, - _path: web::Path, -) -> Result { - todo!() -} diff --git a/src/updates/mod.rs b/src/updates/mod.rs index 96ad3e16c..d92a3b16f 100644 --- a/src/updates/mod.rs +++ b/src/updates/mod.rs @@ -6,6 +6,7 @@ use std::io; use std::sync::Arc; use std::ops::Deref; use std::fs::create_dir_all; +use std::collections::HashMap; use anyhow::Result; use byte_unit::Byte; @@ -21,6 +22,8 @@ use structopt::StructOpt; use crate::option::Opt; +pub type UpdateStatusResponse = UpdateStatus; + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type")] pub enum UpdateMeta { @@ -231,7 +234,8 @@ impl UpdateHandler { // We transpose the settings JSON struct into a real setting update. if let Some(ref facet_types) = settings.faceted_attributes { - builder.set_faceted_fields(facet_types.clone()); + let facet_types = facet_types.clone().unwrap_or_else(|| HashMap::new()); + builder.set_faceted_fields(facet_types); } // We transpose the settings JSON struct into a real setting update. @@ -245,7 +249,7 @@ impl UpdateHandler { let result = builder.execute(|indexing_step, update_id| info!("update {}: {:?}", update_id, indexing_step)); match result { - Ok(_count) => wtxn + Ok(()) => wtxn .commit() .and(Ok(UpdateResult::Other)) .map_err(Into::into), @@ -316,7 +320,7 @@ impl UpdateQueue { } #[inline] - pub fn get_update_status(&self, update_id: u64) -> Result>> { + pub fn get_update_status(&self, update_id: u64) -> Result> { Ok(self.inner.meta(update_id)?) } } diff --git a/src/updates/settings.rs b/src/updates/settings.rs index 58414152a..91381edc5 100644 --- a/src/updates/settings.rs +++ b/src/updates/settings.rs @@ -11,7 +11,7 @@ where T: Deserialize<'de>, Deserialize::deserialize(deserializer).map(Some) } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct Settings { @@ -30,7 +30,7 @@ pub struct Settings { pub searchable_attributes: Option>>, #[serde(default)] - pub faceted_attributes: Option>, + pub faceted_attributes: Option>>, #[serde( default, @@ -40,6 +40,17 @@ pub struct Settings { pub criteria: Option>>, } +impl Settings { + pub fn cleared() -> Self { + Self { + displayed_attributes: Some(None), + searchable_attributes: Some(None), + faceted_attributes: Some(None), + criteria: Some(None), + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(deny_unknown_fields)] @@ -48,4 +59,3 @@ pub struct Facets { pub level_group_size: Option, pub min_level_size: Option, } -