mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-30 08:44:27 +01:00
Merge #914
914: lazily create an index on documents push r=LegendreM a=qdequele Create an index if it's possible when a user trying to send data to a non-existing index. https://github.com/meilisearch/MeiliSearch/issues/918 Co-authored-by: qdequele <quentin@meilisearch.com> Co-authored-by: qdequele <quentin@dequelen.me>
This commit is contained in:
commit
29b8810db8
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1914,7 +1914,8 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pest"
|
name = "pest"
|
||||||
version = "2.1.3"
|
version = "2.1.3"
|
||||||
source = "git+https://github.com/pest-parser/pest.git?rev=51fd1d49f1041f7839975664ef71fe15c7dcaf67#51fd1d49f1041f7839975664ef71fe15c7dcaf67"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ucd-trie",
|
"ucd-trie",
|
||||||
]
|
]
|
||||||
@ -1922,8 +1923,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pest"
|
name = "pest"
|
||||||
version = "2.1.3"
|
version = "2.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/pest-parser/pest.git?rev=51fd1d49f1041f7839975664ef71fe15c7dcaf67#51fd1d49f1041f7839975664ef71fe15c7dcaf67"
|
||||||
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ucd-trie",
|
"ucd-trie",
|
||||||
]
|
]
|
||||||
|
@ -3,9 +3,10 @@ use std::ops::Deref;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use meilisearch_core::{Database, DatabaseOptions};
|
use meilisearch_core::{Database, DatabaseOptions, Index};
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
|
|
||||||
|
use crate::error::{Error as MSError, ResponseError};
|
||||||
use crate::index_update_callback;
|
use crate::index_update_callback;
|
||||||
use crate::option::Opt;
|
use crate::option::Opt;
|
||||||
|
|
||||||
@ -102,4 +103,60 @@ impl Data {
|
|||||||
|
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_index(&self, uid: &str) -> Result<Index, ResponseError> {
|
||||||
|
if !uid
|
||||||
|
.chars()
|
||||||
|
.all(|x| x.is_ascii_alphanumeric() || x == '-' || x == '_')
|
||||||
|
{
|
||||||
|
return Err(MSError::InvalidIndexUid.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let created_index = self.db.create_index(&uid).map_err(|e| match e {
|
||||||
|
meilisearch_core::Error::IndexAlreadyExists => e.into(),
|
||||||
|
_ => ResponseError::from(MSError::create_index(e)),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.db.main_write::<_, _, ResponseError>(|mut writer| {
|
||||||
|
created_index.main.put_name(&mut writer, uid)?;
|
||||||
|
|
||||||
|
created_index
|
||||||
|
.main
|
||||||
|
.created_at(&writer)?
|
||||||
|
.ok_or(MSError::internal("Impossible to read created at"))?;
|
||||||
|
|
||||||
|
created_index
|
||||||
|
.main
|
||||||
|
.updated_at(&writer)?
|
||||||
|
.ok_or(MSError::internal("Impossible to read updated at"))?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(created_index)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_create_index<F, R>(&self, uid: &str, f: F) -> Result<R, ResponseError>
|
||||||
|
where
|
||||||
|
F: FnOnce(&Index) -> Result<R, ResponseError>,
|
||||||
|
{
|
||||||
|
let mut index_has_been_created = false;
|
||||||
|
|
||||||
|
let index = match self.db.open_index(&uid) {
|
||||||
|
Some(index) => index,
|
||||||
|
None => {
|
||||||
|
index_has_been_created = true;
|
||||||
|
self.create_index(&uid)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match f(&index) {
|
||||||
|
Ok(r) => Ok(r),
|
||||||
|
Err(err) => {
|
||||||
|
if index_has_been_created {
|
||||||
|
let _ = self.db.delete_index(&uid);
|
||||||
|
}
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,8 @@ async fn get_document(
|
|||||||
|
|
||||||
let reader = data.db.main_read_txn()?;
|
let reader = data.db.main_read_txn()?;
|
||||||
|
|
||||||
let internal_id = index.main
|
let internal_id = index
|
||||||
|
.main
|
||||||
.external_to_internal_docid(&reader, &path.document_id)?
|
.external_to_internal_docid(&reader, &path.document_id)?
|
||||||
.ok_or(Error::document_not_found(&path.document_id))?;
|
.ok_or(Error::document_not_found(&path.document_id))?;
|
||||||
|
|
||||||
@ -166,47 +167,41 @@ async fn update_multiple_documents(
|
|||||||
body: web::Json<Vec<Document>>,
|
body: web::Json<Vec<Document>>,
|
||||||
is_partial: bool,
|
is_partial: bool,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let reader = data.db.main_read_txn()?;
|
||||||
.open_index(&path.index_uid)
|
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
|
||||||
|
|
||||||
let reader = data.db.main_read_txn()?;
|
let mut schema = index
|
||||||
|
.main
|
||||||
|
.schema(&reader)?
|
||||||
|
.ok_or(meilisearch_core::Error::SchemaMissing)?;
|
||||||
|
|
||||||
let mut schema = index
|
if schema.primary_key().is_none() {
|
||||||
.main
|
let id = match ¶ms.primary_key {
|
||||||
.schema(&reader)?
|
Some(id) => id.to_string(),
|
||||||
.ok_or(meilisearch_core::Error::SchemaMissing)?;
|
None => body
|
||||||
|
.first()
|
||||||
|
.and_then(find_primary_key)
|
||||||
|
.ok_or(meilisearch_core::Error::MissingPrimaryKey)?,
|
||||||
|
};
|
||||||
|
|
||||||
if schema.primary_key().is_none() {
|
schema.set_primary_key(&id).map_err(Error::bad_request)?;
|
||||||
let id = match ¶ms.primary_key {
|
|
||||||
Some(id) => id.to_string(),
|
data.db.main_write(|w| index.main.put_schema(w, &schema))?;
|
||||||
None => body
|
}
|
||||||
.first()
|
|
||||||
.and_then(find_primary_key)
|
let mut document_addition = if is_partial {
|
||||||
.ok_or(meilisearch_core::Error::MissingPrimaryKey)?
|
index.documents_partial_addition()
|
||||||
|
} else {
|
||||||
|
index.documents_addition()
|
||||||
};
|
};
|
||||||
|
|
||||||
schema
|
for document in body.into_inner() {
|
||||||
.set_primary_key(&id)
|
document_addition.update_document(document);
|
||||||
.map_err(Error::bad_request)?;
|
}
|
||||||
|
|
||||||
data.db.main_write(|w| index.main.put_schema(w, &schema))?;
|
Ok(data.db.update_write(|w| document_addition.finalize(w))?)
|
||||||
}
|
})?;
|
||||||
|
return Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)));
|
||||||
let mut document_addition = if is_partial {
|
|
||||||
index.documents_partial_addition()
|
|
||||||
} else {
|
|
||||||
index.documents_addition()
|
|
||||||
};
|
|
||||||
|
|
||||||
for document in body.into_inner() {
|
|
||||||
document_addition.update_document(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| document_addition.finalize(w))?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
#[post("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||||
@ -243,7 +238,6 @@ async fn delete_documents(
|
|||||||
.open_index(&path.index_uid)
|
.open_index(&path.index_uid)
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
.ok_or(Error::index_not_found(&path.index_uid))?;
|
||||||
|
|
||||||
|
|
||||||
let mut documents_deletion = index.documents_deletion();
|
let mut documents_deletion = index.documents_deletion();
|
||||||
|
|
||||||
for document_id in body.into_inner() {
|
for document_id in body.into_inner() {
|
||||||
|
@ -53,13 +53,12 @@ async fn update_all(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<Settings>,
|
body: web::Json<Settings>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let settings = body
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.into_inner()
|
Ok(data.db.update_write::<_, _, ResponseError>(|writer| {
|
||||||
.to_update()
|
let settings = body.into_inner().to_update().map_err(Error::bad_request)?;
|
||||||
.map_err(Error::bad_request)?;
|
let update_id = index.settings_update(writer, settings)?;
|
||||||
|
Ok(update_id)
|
||||||
let update_id = data.db.update_write::<_, _, Error>(|writer| {
|
})?)
|
||||||
update_all_settings_txn(&data, settings, &path.index_uid, writer)
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
@ -71,11 +70,7 @@ pub fn get_all_sync(data: &web::Data<Data>, reader: &MainReader, index_uid: &str
|
|||||||
.open_index(index_uid)
|
.open_index(index_uid)
|
||||||
.ok_or(Error::index_not_found(index_uid))?;
|
.ok_or(Error::index_not_found(index_uid))?;
|
||||||
|
|
||||||
let stop_words: BTreeSet<String> = index
|
let stop_words: BTreeSet<String> = index.main.stop_words(&reader)?.into_iter().collect();
|
||||||
.main
|
|
||||||
.stop_words(reader)?
|
|
||||||
.into_iter()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let synonyms_list = index.main.synonyms(reader)?;
|
let synonyms_list = index.main.synonyms(reader)?;
|
||||||
|
|
||||||
@ -94,22 +89,19 @@ pub fn get_all_sync(data: &web::Data<Data>, reader: &MainReader, index_uid: &str
|
|||||||
.map(|r| r.to_string())
|
.map(|r| r.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let schema = index.main.schema(&reader)?;
|
||||||
let schema = index.main.schema(reader)?;
|
|
||||||
|
|
||||||
let distinct_attribute = match (index.main.distinct_attribute(reader)?, &schema) {
|
let distinct_attribute = match (index.main.distinct_attribute(reader)?, &schema) {
|
||||||
(Some(id), Some(schema)) => schema.name(id).map(str::to_string),
|
(Some(id), Some(schema)) => schema.name(id).map(str::to_string),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let attributes_for_faceting = match (&schema, &index.main.attributes_for_faceting(reader)?) {
|
let attributes_for_faceting = match (&schema, &index.main.attributes_for_faceting(&reader)?) {
|
||||||
(Some(schema), Some(attrs)) => {
|
(Some(schema), Some(attrs)) => attrs
|
||||||
attrs
|
.iter()
|
||||||
.iter()
|
.filter_map(|&id| schema.name(id))
|
||||||
.filter_map(|&id| schema.name(id))
|
.map(str::to_string)
|
||||||
.map(str::to_string)
|
.collect(),
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,7 +151,9 @@ async fn delete_all(
|
|||||||
attributes_for_faceting: UpdateState::Clear,
|
attributes_for_faceting: UpdateState::Clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -198,18 +192,17 @@ async fn update_rules(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<Option<Vec<String>>>,
|
body: web::Json<Option<Vec<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let settings = Settings {
|
||||||
.open_index(&path.index_uid)
|
ranking_rules: Some(body.into_inner()),
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
..Settings::default()
|
||||||
|
};
|
||||||
|
|
||||||
let settings = Settings {
|
let settings = settings.to_update().map_err(Error::bad_request)?;
|
||||||
ranking_rules: Some(body.into_inner()),
|
Ok(data
|
||||||
..Settings::default()
|
.db
|
||||||
};
|
.update_write(|w| index.settings_update(w, settings))?)
|
||||||
|
})?;
|
||||||
let settings = settings.to_update().map_err(Error::bad_request)?;
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -232,7 +225,9 @@ async fn delete_rules(
|
|||||||
..SettingsUpdate::default()
|
..SettingsUpdate::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -269,18 +264,17 @@ async fn update_distinct(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<Option<String>>,
|
body: web::Json<Option<String>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let settings = Settings {
|
||||||
.open_index(&path.index_uid)
|
distinct_attribute: Some(body.into_inner()),
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
..Settings::default()
|
||||||
|
};
|
||||||
|
|
||||||
let settings = Settings {
|
let settings = settings.to_update().map_err(Error::bad_request)?;
|
||||||
distinct_attribute: Some(body.into_inner()),
|
Ok(data
|
||||||
..Settings::default()
|
.db
|
||||||
};
|
.update_write(|w| index.settings_update(w, settings))?)
|
||||||
|
})?;
|
||||||
let settings = settings.to_update().map_err(Error::bad_request)?;
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -303,7 +297,9 @@ async fn delete_distinct(
|
|||||||
..SettingsUpdate::default()
|
..SettingsUpdate::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -322,8 +318,7 @@ async fn get_searchable(
|
|||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
.ok_or(Error::index_not_found(&path.index_uid))?;
|
||||||
let reader = data.db.main_read_txn()?;
|
let reader = data.db.main_read_txn()?;
|
||||||
let schema = index.main.schema(&reader)?;
|
let schema = index.main.schema(&reader)?;
|
||||||
let searchable_attributes: Option<Vec<String>> =
|
let searchable_attributes: Option<Vec<String>> = schema.as_ref().map(get_indexed_attributes);
|
||||||
schema.as_ref().map(get_indexed_attributes);
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(searchable_attributes))
|
Ok(HttpResponse::Ok().json(searchable_attributes))
|
||||||
}
|
}
|
||||||
@ -337,19 +332,18 @@ async fn update_searchable(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<Option<Vec<String>>>,
|
body: web::Json<Option<Vec<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let settings = Settings {
|
||||||
.open_index(&path.index_uid)
|
searchable_attributes: Some(body.into_inner()),
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
..Settings::default()
|
||||||
|
};
|
||||||
|
|
||||||
let settings = Settings {
|
let settings = settings.to_update().map_err(Error::bad_request)?;
|
||||||
searchable_attributes: Some(body.into_inner()),
|
|
||||||
..Settings::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let settings = settings.to_update().map_err(Error::bad_request)?;
|
Ok(data
|
||||||
|
.db
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
.update_write(|w| index.settings_update(w, settings))?)
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -372,7 +366,9 @@ async fn delete_searchable(
|
|||||||
..SettingsUpdate::default()
|
..SettingsUpdate::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -407,18 +403,17 @@ async fn update_displayed(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<Option<BTreeSet<String>>>,
|
body: web::Json<Option<BTreeSet<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let settings = Settings {
|
||||||
.open_index(&path.index_uid)
|
displayed_attributes: Some(body.into_inner()),
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
..Settings::default()
|
||||||
|
};
|
||||||
|
|
||||||
let settings = Settings {
|
let settings = settings.to_update().map_err(Error::bad_request)?;
|
||||||
displayed_attributes: Some(body.into_inner()),
|
Ok(data
|
||||||
..Settings::default()
|
.db
|
||||||
};
|
.update_write(|w| index.settings_update(w, settings))?)
|
||||||
|
})?;
|
||||||
let settings = settings.to_update().map_err(Error::bad_request)?;
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -441,7 +436,9 @@ async fn delete_displayed(
|
|||||||
..SettingsUpdate::default()
|
..SettingsUpdate::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -459,20 +456,16 @@ async fn get_attributes_for_faceting(
|
|||||||
.open_index(&path.index_uid)
|
.open_index(&path.index_uid)
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
.ok_or(Error::index_not_found(&path.index_uid))?;
|
||||||
|
|
||||||
let attributes_for_faceting = data
|
let attributes_for_faceting = data.db.main_read::<_, _, ResponseError>(|reader| {
|
||||||
.db
|
|
||||||
.main_read::<_, _, ResponseError>(|reader| {
|
|
||||||
let schema = index.main.schema(reader)?;
|
let schema = index.main.schema(reader)?;
|
||||||
let attrs = index.main.attributes_for_faceting(reader)?;
|
let attrs = index.main.attributes_for_faceting(reader)?;
|
||||||
let attr_names = match (&schema, &attrs) {
|
let attr_names = match (&schema, &attrs) {
|
||||||
(Some(schema), Some(attrs)) => {
|
(Some(schema), Some(attrs)) => attrs
|
||||||
attrs
|
.iter()
|
||||||
.iter()
|
.filter_map(|&id| schema.name(id))
|
||||||
.filter_map(|&id| schema.name(id))
|
.map(str::to_string)
|
||||||
.map(str::to_string)
|
.collect(),
|
||||||
.collect()
|
_ => vec![],
|
||||||
}
|
|
||||||
_ => vec![]
|
|
||||||
};
|
};
|
||||||
Ok(attr_names)
|
Ok(attr_names)
|
||||||
})?;
|
})?;
|
||||||
@ -489,18 +482,17 @@ async fn update_attributes_for_faceting(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<Option<Vec<String>>>,
|
body: web::Json<Option<Vec<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let settings = Settings {
|
||||||
.open_index(&path.index_uid)
|
attributes_for_faceting: Some(body.into_inner()),
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
..Settings::default()
|
||||||
|
};
|
||||||
|
|
||||||
let settings = Settings {
|
let settings = settings.to_update().map_err(Error::bad_request)?;
|
||||||
attributes_for_faceting: Some(body.into_inner()),
|
Ok(data
|
||||||
..Settings::default()
|
.db
|
||||||
};
|
.update_write(|w| index.settings_update(w, settings))?)
|
||||||
|
})?;
|
||||||
let settings = settings.to_update().map_err(Error::bad_request)?;
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -523,7 +515,9 @@ async fn delete_attributes_for_faceting(
|
|||||||
..SettingsUpdate::default()
|
..SettingsUpdate::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -532,7 +526,8 @@ fn get_indexed_attributes(schema: &Schema) -> Vec<String> {
|
|||||||
if schema.is_indexed_all() {
|
if schema.is_indexed_all() {
|
||||||
["*"].iter().map(|s| s.to_string()).collect()
|
["*"].iter().map(|s| s.to_string()).collect()
|
||||||
} else {
|
} else {
|
||||||
schema.indexed_name()
|
schema
|
||||||
|
.indexed_name()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect()
|
.collect()
|
||||||
@ -543,7 +538,8 @@ fn get_displayed_attributes(schema: &Schema) -> BTreeSet<String> {
|
|||||||
if schema.is_displayed_all() {
|
if schema.is_displayed_all() {
|
||||||
["*"].iter().map(|s| s.to_string()).collect()
|
["*"].iter().map(|s| s.to_string()).collect()
|
||||||
} else {
|
} else {
|
||||||
schema.displayed_name()
|
schema
|
||||||
|
.displayed_name()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -39,17 +39,16 @@ async fn update(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<BTreeSet<String>>,
|
body: web::Json<BTreeSet<String>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let settings = SettingsUpdate {
|
||||||
.open_index(&path.index_uid)
|
stop_words: UpdateState::Update(body.into_inner()),
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
..SettingsUpdate::default()
|
||||||
|
};
|
||||||
|
|
||||||
let settings = SettingsUpdate {
|
Ok(data
|
||||||
stop_words: UpdateState::Update(body.into_inner()),
|
.db
|
||||||
..SettingsUpdate::default()
|
.update_write(|w| index.settings_update(w, settings))?)
|
||||||
};
|
})?;
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -72,7 +71,9 @@ async fn delete(
|
|||||||
..SettingsUpdate::default()
|
..SettingsUpdate::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
|
@ -50,17 +50,16 @@ async fn update(
|
|||||||
path: web::Path<IndexParam>,
|
path: web::Path<IndexParam>,
|
||||||
body: web::Json<BTreeMap<String, Vec<String>>>,
|
body: web::Json<BTreeMap<String, Vec<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index = data
|
let update_id = data.get_or_create_index(&path.index_uid, |index| {
|
||||||
.db
|
let settings = SettingsUpdate {
|
||||||
.open_index(&path.index_uid)
|
synonyms: UpdateState::Update(body.into_inner()),
|
||||||
.ok_or(Error::index_not_found(&path.index_uid))?;
|
..SettingsUpdate::default()
|
||||||
|
};
|
||||||
|
|
||||||
let settings = SettingsUpdate {
|
Ok(data
|
||||||
synonyms: UpdateState::Update(body.into_inner()),
|
.db
|
||||||
..SettingsUpdate::default()
|
.update_write(|w| index.settings_update(w, settings))?)
|
||||||
};
|
})?;
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
@ -83,7 +82,9 @@ async fn delete(
|
|||||||
..SettingsUpdate::default()
|
..SettingsUpdate::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_id = data.db.update_write(|w| index.settings_update(w, settings))?;
|
let update_id = data
|
||||||
|
.db
|
||||||
|
.update_write(|w| index.settings_update(w, settings))?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,24 @@ use meilisearch_http::option::Opt;
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! test_post_get_search {
|
macro_rules! test_post_get_search {
|
||||||
($server:expr, $query:expr, |$response:ident, $status_code:ident | $block:expr) => {
|
($server:expr, $query:expr, |$response:ident, $status_code:ident | $block:expr) => {
|
||||||
let post_query: meilisearch_http::routes::search::SearchQueryPost = serde_json::from_str(&$query.clone().to_string()).unwrap();
|
let post_query: meilisearch_http::routes::search::SearchQueryPost =
|
||||||
|
serde_json::from_str(&$query.clone().to_string()).unwrap();
|
||||||
let get_query: meilisearch_http::routes::search::SearchQuery = post_query.into();
|
let get_query: meilisearch_http::routes::search::SearchQuery = post_query.into();
|
||||||
let get_query = ::serde_url_params::to_string(&get_query).unwrap();
|
let get_query = ::serde_url_params::to_string(&get_query).unwrap();
|
||||||
let ($response, $status_code) = $server.search_get(&get_query).await;
|
let ($response, $status_code) = $server.search_get(&get_query).await;
|
||||||
let _ =::std::panic::catch_unwind(|| $block)
|
let _ = ::std::panic::catch_unwind(|| $block).map_err(|e| {
|
||||||
.map_err(|e| panic!("panic in get route: {:?}", e.downcast_ref::<&str>().unwrap()));
|
panic!(
|
||||||
|
"panic in get route: {:?}",
|
||||||
|
e.downcast_ref::<&str>().unwrap()
|
||||||
|
)
|
||||||
|
});
|
||||||
let ($response, $status_code) = $server.search_post($query).await;
|
let ($response, $status_code) = $server.search_post($query).await;
|
||||||
let _ = ::std::panic::catch_unwind(|| $block)
|
let _ = ::std::panic::catch_unwind(|| $block).map_err(|e| {
|
||||||
.map_err(|e| panic!("panic in post route: {:?}", e.downcast_ref::<&str>().unwrap()));
|
panic!(
|
||||||
|
"panic in post route: {:?}",
|
||||||
|
e.downcast_ref::<&str>().unwrap()
|
||||||
|
)
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +70,6 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn test_server() -> Self {
|
pub async fn test_server() -> Self {
|
||||||
|
|
||||||
let mut server = Self::with_uid("test");
|
let mut server = Self::with_uid("test");
|
||||||
|
|
||||||
let body = json!({
|
let body = json!({
|
||||||
@ -151,7 +159,8 @@ impl Server {
|
|||||||
pub async fn get_request(&mut self, url: &str) -> (Value, StatusCode) {
|
pub async fn get_request(&mut self, url: &str) -> (Value, StatusCode) {
|
||||||
eprintln!("get_request: {}", url);
|
eprintln!("get_request: {}", url);
|
||||||
|
|
||||||
let mut app = test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
let mut app =
|
||||||
|
test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
||||||
|
|
||||||
let req = test::TestRequest::get().uri(url).to_request();
|
let req = test::TestRequest::get().uri(url).to_request();
|
||||||
let res = test::call_service(&mut app, req).await;
|
let res = test::call_service(&mut app, req).await;
|
||||||
@ -165,7 +174,8 @@ impl Server {
|
|||||||
pub async fn post_request(&self, url: &str, body: Value) -> (Value, StatusCode) {
|
pub async fn post_request(&self, url: &str, body: Value) -> (Value, StatusCode) {
|
||||||
eprintln!("post_request: {}", url);
|
eprintln!("post_request: {}", url);
|
||||||
|
|
||||||
let mut app = test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
let mut app =
|
||||||
|
test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
||||||
|
|
||||||
let req = test::TestRequest::post()
|
let req = test::TestRequest::post()
|
||||||
.uri(url)
|
.uri(url)
|
||||||
@ -183,8 +193,7 @@ impl Server {
|
|||||||
eprintln!("post_request_async: {}", url);
|
eprintln!("post_request_async: {}", url);
|
||||||
|
|
||||||
let (response, status_code) = self.post_request(url, body).await;
|
let (response, status_code) = self.post_request(url, body).await;
|
||||||
// eprintln!("response: {}", response);
|
eprintln!("response: {}", response);
|
||||||
assert_eq!(status_code, 202);
|
|
||||||
assert!(response["updateId"].as_u64().is_some());
|
assert!(response["updateId"].as_u64().is_some());
|
||||||
self.wait_update_id(response["updateId"].as_u64().unwrap())
|
self.wait_update_id(response["updateId"].as_u64().unwrap())
|
||||||
.await;
|
.await;
|
||||||
@ -194,7 +203,8 @@ impl Server {
|
|||||||
pub async fn put_request(&mut self, url: &str, body: Value) -> (Value, StatusCode) {
|
pub async fn put_request(&mut self, url: &str, body: Value) -> (Value, StatusCode) {
|
||||||
eprintln!("put_request: {}", url);
|
eprintln!("put_request: {}", url);
|
||||||
|
|
||||||
let mut app = test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
let mut app =
|
||||||
|
test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
||||||
|
|
||||||
let req = test::TestRequest::put()
|
let req = test::TestRequest::put()
|
||||||
.uri(url)
|
.uri(url)
|
||||||
@ -222,7 +232,8 @@ impl Server {
|
|||||||
pub async fn delete_request(&mut self, url: &str) -> (Value, StatusCode) {
|
pub async fn delete_request(&mut self, url: &str) -> (Value, StatusCode) {
|
||||||
eprintln!("delete_request: {}", url);
|
eprintln!("delete_request: {}", url);
|
||||||
|
|
||||||
let mut app = test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
let mut app =
|
||||||
|
test::init_service(meilisearch_http::create_app(&self.data).wrap(NormalizePath)).await;
|
||||||
|
|
||||||
let req = test::TestRequest::delete().uri(url).to_request();
|
let req = test::TestRequest::delete().uri(url).to_request();
|
||||||
let res = test::call_service(&mut app, req).await;
|
let res = test::call_service(&mut app, req).await;
|
||||||
@ -340,9 +351,9 @@ impl Server {
|
|||||||
self.delete_request_async(&url).await
|
self.delete_request_async(&url).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_multiple_documents(&mut self, body: Value) {
|
pub async fn delete_multiple_documents(&mut self, body: Value) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/documents/delete-batch", self.uid);
|
let url = format!("/indexes/{}/documents/delete-batch", self.uid);
|
||||||
self.post_request_async(&url, body).await;
|
self.post_request_async(&url, body).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all_settings(&mut self) -> (Value, StatusCode) {
|
pub async fn get_all_settings(&mut self) -> (Value, StatusCode) {
|
||||||
@ -355,6 +366,11 @@ impl Server {
|
|||||||
self.post_request_async(&url, body).await;
|
self.post_request_async(&url, body).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn update_all_settings_sync(&mut self, body: Value) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings", self.uid);
|
||||||
|
self.post_request(&url, body).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete_all_settings(&mut self) -> (Value, StatusCode) {
|
pub async fn delete_all_settings(&mut self) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/settings", self.uid);
|
let url = format!("/indexes/{}/settings", self.uid);
|
||||||
self.delete_request_async(&url).await
|
self.delete_request_async(&url).await
|
||||||
@ -390,6 +406,11 @@ impl Server {
|
|||||||
self.post_request_async(&url, body).await;
|
self.post_request_async(&url, body).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn update_distinct_attribute_sync(&mut self, body: Value) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/distinct-attribute", self.uid);
|
||||||
|
self.post_request(&url, body).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete_distinct_attribute(&mut self) -> (Value, StatusCode) {
|
pub async fn delete_distinct_attribute(&mut self) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/settings/distinct-attribute", self.uid);
|
let url = format!("/indexes/{}/settings/distinct-attribute", self.uid);
|
||||||
self.delete_request_async(&url).await
|
self.delete_request_async(&url).await
|
||||||
@ -410,6 +431,11 @@ impl Server {
|
|||||||
self.post_request_async(&url, body).await;
|
self.post_request_async(&url, body).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn update_searchable_attributes_sync(&mut self, body: Value) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/searchable-attributes", self.uid);
|
||||||
|
self.post_request(&url, body).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete_searchable_attributes(&mut self) -> (Value, StatusCode) {
|
pub async fn delete_searchable_attributes(&mut self) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/settings/searchable-attributes", self.uid);
|
let url = format!("/indexes/{}/settings/searchable-attributes", self.uid);
|
||||||
self.delete_request_async(&url).await
|
self.delete_request_async(&url).await
|
||||||
@ -425,11 +451,39 @@ impl Server {
|
|||||||
self.post_request_async(&url, body).await;
|
self.post_request_async(&url, body).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn update_displayed_attributes_sync(&mut self, body: Value) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/displayed-attributes", self.uid);
|
||||||
|
self.post_request(&url, body).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete_displayed_attributes(&mut self) -> (Value, StatusCode) {
|
pub async fn delete_displayed_attributes(&mut self) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/settings/displayed-attributes", self.uid);
|
let url = format!("/indexes/{}/settings/displayed-attributes", self.uid);
|
||||||
self.delete_request_async(&url).await
|
self.delete_request_async(&url).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_attributes_for_faceting(&mut self) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/attributes-for-faceting", self.uid);
|
||||||
|
self.get_request(&url).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_attributes_for_faceting(&mut self, body: Value) {
|
||||||
|
let url = format!("/indexes/{}/settings/attributes-for-faceting", self.uid);
|
||||||
|
self.post_request_async(&url, body).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_attributes_for_faceting_sync(
|
||||||
|
&mut self,
|
||||||
|
body: Value,
|
||||||
|
) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/attributes-for-faceting", self.uid);
|
||||||
|
self.post_request(&url, body).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete_attributes_for_faceting(&mut self) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/attributes-for-faceting", self.uid);
|
||||||
|
self.delete_request_async(&url).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_synonyms(&mut self) -> (Value, StatusCode) {
|
pub async fn get_synonyms(&mut self) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/settings/synonyms", self.uid);
|
let url = format!("/indexes/{}/settings/synonyms", self.uid);
|
||||||
self.get_request(&url).await
|
self.get_request(&url).await
|
||||||
@ -440,6 +494,11 @@ impl Server {
|
|||||||
self.post_request_async(&url, body).await;
|
self.post_request_async(&url, body).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn update_synonyms_sync(&mut self, body: Value) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/synonyms", self.uid);
|
||||||
|
self.post_request(&url, body).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete_synonyms(&mut self) -> (Value, StatusCode) {
|
pub async fn delete_synonyms(&mut self) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/settings/synonyms", self.uid);
|
let url = format!("/indexes/{}/settings/synonyms", self.uid);
|
||||||
self.delete_request_async(&url).await
|
self.delete_request_async(&url).await
|
||||||
@ -455,6 +514,11 @@ impl Server {
|
|||||||
self.post_request_async(&url, body).await;
|
self.post_request_async(&url, body).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn update_stop_words_sync(&mut self, body: Value) -> (Value, StatusCode) {
|
||||||
|
let url = format!("/indexes/{}/settings/stop-words", self.uid);
|
||||||
|
self.post_request(&url, body).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn delete_stop_words(&mut self) -> (Value, StatusCode) {
|
pub async fn delete_stop_words(&mut self) -> (Value, StatusCode) {
|
||||||
let url = format!("/indexes/{}/settings/stop-words", self.uid);
|
let url = format!("/indexes/{}/settings/stop-words", self.uid);
|
||||||
self.delete_request_async(&url).await
|
self.delete_request_async(&url).await
|
||||||
|
@ -192,7 +192,9 @@ async fn add_document_with_long_field() {
|
|||||||
"url":"/configuration/app/web.html#locations"
|
"url":"/configuration/app/web.html#locations"
|
||||||
}]);
|
}]);
|
||||||
server.add_or_replace_multiple_documents(body).await;
|
server.add_or_replace_multiple_documents(body).await;
|
||||||
let (response, _status) = server.search_post(json!({ "q": "request_buffering" })).await;
|
let (response, _status) = server
|
||||||
|
.search_post(json!({ "q": "request_buffering" }))
|
||||||
|
.await;
|
||||||
assert!(!response["hits"].as_array().unwrap().is_empty());
|
assert!(!response["hits"].as_array().unwrap().is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,5 +215,8 @@ async fn documents_with_same_id_are_overwritten() {
|
|||||||
server.add_or_replace_multiple_documents(documents).await;
|
server.add_or_replace_multiple_documents(documents).await;
|
||||||
let (response, _status) = server.get_all_documents().await;
|
let (response, _status) = server.get_all_documents().await;
|
||||||
assert_eq!(response.as_array().unwrap().len(), 1);
|
assert_eq!(response.as_array().unwrap().len(), 1);
|
||||||
assert_eq!(response.as_array().unwrap()[0].as_object().unwrap()["content"], "test2");
|
assert_eq!(
|
||||||
|
response.as_array().unwrap()[0].as_object().unwrap()["content"],
|
||||||
|
"test2"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
446
meilisearch-http/tests/lazy_index_creation.rs
Normal file
446
meilisearch-http/tests/lazy_index_creation.rs
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_pushing_documents() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
|
||||||
|
// 1 - Add documents
|
||||||
|
|
||||||
|
let body = json!([{
|
||||||
|
"title": "Test",
|
||||||
|
"comment": "comment test"
|
||||||
|
}]);
|
||||||
|
|
||||||
|
let url = "/indexes/movies/documents?primaryKey=title";
|
||||||
|
let (response, status_code) = server.post_request(&url, body).await;
|
||||||
|
assert_eq!(status_code, 202);
|
||||||
|
let update_id = response["updateId"].as_u64().unwrap();
|
||||||
|
server.wait_update_id(update_id).await;
|
||||||
|
|
||||||
|
// 3 - Check update success
|
||||||
|
|
||||||
|
let (response, status_code) = server.get_update_status(update_id).await;
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
assert_eq!(response["status"], "processed");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_pushing_documents_and_discover_pk() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
|
||||||
|
// 1 - Add documents
|
||||||
|
|
||||||
|
let body = json!([{
|
||||||
|
"id": 1,
|
||||||
|
"title": "Test",
|
||||||
|
"comment": "comment test"
|
||||||
|
}]);
|
||||||
|
|
||||||
|
let url = "/indexes/movies/documents";
|
||||||
|
let (response, status_code) = server.post_request(&url, body).await;
|
||||||
|
assert_eq!(status_code, 202);
|
||||||
|
let update_id = response["updateId"].as_u64().unwrap();
|
||||||
|
server.wait_update_id(update_id).await;
|
||||||
|
|
||||||
|
// 3 - Check update success
|
||||||
|
|
||||||
|
let (response, status_code) = server.get_update_status(update_id).await;
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
assert_eq!(response["status"], "processed");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_pushing_documents_with_wrong_name() {
|
||||||
|
let server = common::Server::with_uid("wrong&name");
|
||||||
|
|
||||||
|
let body = json!([{
|
||||||
|
"title": "Test",
|
||||||
|
"comment": "comment test"
|
||||||
|
}]);
|
||||||
|
|
||||||
|
let url = "/indexes/wrong&name/documents?primaryKey=title";
|
||||||
|
let (response, status_code) = server.post_request(&url, body).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
assert_eq!(response["errorCode"], "invalid_index_uid");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_add_documents_failed() {
|
||||||
|
let mut server = common::Server::with_uid("wrong&name");
|
||||||
|
|
||||||
|
let body = json!([{
|
||||||
|
"title": "Test",
|
||||||
|
"comment": "comment test"
|
||||||
|
}]);
|
||||||
|
|
||||||
|
let url = "/indexes/wrong&name/documents";
|
||||||
|
let (response, status_code) = server.post_request(&url, body).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
assert_eq!(response["errorCode"], "invalid_index_uid");
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_index().await;
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_settings() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!({
|
||||||
|
"rankingRules": [
|
||||||
|
"typo",
|
||||||
|
"words",
|
||||||
|
"proximity",
|
||||||
|
"attribute",
|
||||||
|
"wordsPosition",
|
||||||
|
"exactness",
|
||||||
|
"desc(registered)",
|
||||||
|
"desc(age)",
|
||||||
|
],
|
||||||
|
"distinctAttribute": "id",
|
||||||
|
"searchableAttributes": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"color",
|
||||||
|
"gender",
|
||||||
|
"email",
|
||||||
|
"phone",
|
||||||
|
"address",
|
||||||
|
"registered",
|
||||||
|
"about"
|
||||||
|
],
|
||||||
|
"displayedAttributes": [
|
||||||
|
"name",
|
||||||
|
"gender",
|
||||||
|
"email",
|
||||||
|
"registered",
|
||||||
|
"age",
|
||||||
|
],
|
||||||
|
"stopWords": [
|
||||||
|
"ad",
|
||||||
|
"in",
|
||||||
|
"ut",
|
||||||
|
],
|
||||||
|
"synonyms": {
|
||||||
|
"road": ["street", "avenue"],
|
||||||
|
"street": ["avenue"],
|
||||||
|
},
|
||||||
|
"attributesForFaceting": ["name"],
|
||||||
|
});
|
||||||
|
|
||||||
|
server.update_all_settings(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_settings_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!({
|
||||||
|
"rankingRules": [
|
||||||
|
"other",
|
||||||
|
"words",
|
||||||
|
"proximity",
|
||||||
|
"attribute",
|
||||||
|
"wordsPosition",
|
||||||
|
"exactness",
|
||||||
|
"desc(registered)",
|
||||||
|
"desc(age)",
|
||||||
|
],
|
||||||
|
"distinctAttribute": "id",
|
||||||
|
"searchableAttributes": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"color",
|
||||||
|
"gender",
|
||||||
|
"email",
|
||||||
|
"phone",
|
||||||
|
"address",
|
||||||
|
"registered",
|
||||||
|
"about"
|
||||||
|
],
|
||||||
|
"displayedAttributes": [
|
||||||
|
"name",
|
||||||
|
"gender",
|
||||||
|
"email",
|
||||||
|
"registered",
|
||||||
|
"age",
|
||||||
|
],
|
||||||
|
"stopWords": [
|
||||||
|
"ad",
|
||||||
|
"in",
|
||||||
|
"ut",
|
||||||
|
],
|
||||||
|
"synonyms": {
|
||||||
|
"road": ["street", "avenue"],
|
||||||
|
"street": ["avenue"],
|
||||||
|
},
|
||||||
|
"anotherSettings": ["name"],
|
||||||
|
});
|
||||||
|
|
||||||
|
let (_, status_code) = server.update_all_settings_sync(body.clone()).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_ranking_rules() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!([
|
||||||
|
"typo",
|
||||||
|
"words",
|
||||||
|
"proximity",
|
||||||
|
"attribute",
|
||||||
|
"wordsPosition",
|
||||||
|
"exactness",
|
||||||
|
"desc(registered)",
|
||||||
|
"desc(age)",
|
||||||
|
]);
|
||||||
|
|
||||||
|
server.update_ranking_rules(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_ranking_rules_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!({
|
||||||
|
"rankingRules": 123,
|
||||||
|
});
|
||||||
|
|
||||||
|
let (_, status_code) = server.update_ranking_rules_sync(body.clone()).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_distinct_attribute() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!("type");
|
||||||
|
|
||||||
|
server.update_distinct_attribute(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_distinct_attribute_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(123);
|
||||||
|
|
||||||
|
let (resp, status_code) = server.update_distinct_attribute_sync(body.clone()).await;
|
||||||
|
eprintln!("resp: {:?}", resp);
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (resp, status_code) = server.get_all_settings().await;
|
||||||
|
eprintln!("resp: {:?}", resp);
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_searchable_attributes() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(["title", "description"]);
|
||||||
|
|
||||||
|
server.update_searchable_attributes(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_searchable_attributes_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(123);
|
||||||
|
|
||||||
|
let (_, status_code) = server.update_searchable_attributes_sync(body.clone()).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_displayed_attributes() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(["title", "description"]);
|
||||||
|
|
||||||
|
server.update_displayed_attributes(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_displayed_attributes_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(123);
|
||||||
|
|
||||||
|
let (_, status_code) = server.update_displayed_attributes_sync(body.clone()).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_attributes_for_faceting() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(["title", "description"]);
|
||||||
|
|
||||||
|
server.update_attributes_for_faceting(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_attributes_for_faceting_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(123);
|
||||||
|
|
||||||
|
let (_, status_code) = server
|
||||||
|
.update_attributes_for_faceting_sync(body.clone())
|
||||||
|
.await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_synonyms() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!({
|
||||||
|
"road": ["street", "avenue"],
|
||||||
|
"street": ["avenue"],
|
||||||
|
});
|
||||||
|
|
||||||
|
server.update_synonyms(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_synonyms_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(123);
|
||||||
|
|
||||||
|
let (_, status_code) = server.update_synonyms_sync(body.clone()).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_stop_words() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(["le", "la", "les"]);
|
||||||
|
|
||||||
|
server.update_stop_words(body.clone()).await;
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn create_index_lazy_by_sending_stop_words_with_error() {
|
||||||
|
let mut server = common::Server::with_uid("movies");
|
||||||
|
// 2 - Send the settings
|
||||||
|
|
||||||
|
let body = json!(123);
|
||||||
|
|
||||||
|
let (_, status_code) = server.update_stop_words_sync(body.clone()).await;
|
||||||
|
assert_eq!(status_code, 400);
|
||||||
|
|
||||||
|
// 3 - Get all settings and compare to the previous one
|
||||||
|
|
||||||
|
let (_, status_code) = server.get_all_settings().await;
|
||||||
|
|
||||||
|
assert_eq!(status_code, 404);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user