mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-22 10:07:40 +08:00
clean code, and fix errors
This commit is contained in:
parent
29b1f55bb0
commit
7c9eaaeadb
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# the milli project is a library
|
||||||
|
/target
|
3447
Cargo.lock
generated
Normal file
3447
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
54
Cargo.toml
54
Cargo.toml
@ -1,20 +1,16 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "meilisearch-http"
|
authors = ["Quentin de Quelen <quentin@dequelen.me>", "Clément Renault <clement@meilisearch.com>"]
|
||||||
description = "MeiliSearch HTTP server"
|
description = "MeiliSearch HTTP server"
|
||||||
version = "0.17.0"
|
|
||||||
license = "MIT"
|
|
||||||
authors = [
|
|
||||||
"Quentin de Quelen <quentin@dequelen.me>",
|
|
||||||
"Clément Renault <clement@meilisearch.com>",
|
|
||||||
]
|
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
license = "MIT"
|
||||||
|
name = "meilisearch-http"
|
||||||
|
version = "0.17.0"
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "meilisearch"
|
name = "meilisearch"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[features]
|
[build-dependencies]
|
||||||
default = ["sentry"]
|
vergen = "3.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-cors = "0.5.3"
|
actix-cors = "0.5.3"
|
||||||
@ -22,6 +18,7 @@ actix-http = "2"
|
|||||||
actix-rt = "1"
|
actix-rt = "1"
|
||||||
actix-service = "1.0.6"
|
actix-service = "1.0.6"
|
||||||
actix-web = { version = "3.3.2", features = ["rustls"] }
|
actix-web = { version = "3.3.2", features = ["rustls"] }
|
||||||
|
byte-unit = { version = "4.0.9", default-features = false, features = ["std"] }
|
||||||
bytes = "0.6.0"
|
bytes = "0.6.0"
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
crossbeam-channel = "0.5.0"
|
crossbeam-channel = "0.5.0"
|
||||||
@ -29,19 +26,16 @@ env_logger = "0.8.2"
|
|||||||
flate2 = "1.0.18"
|
flate2 = "1.0.18"
|
||||||
futures = "0.3.7"
|
futures = "0.3.7"
|
||||||
http = "0.2.1"
|
http = "0.2.1"
|
||||||
indexmap = { version = "1.3.2", features = ["serde-1"] }
|
indexmap = { version = "1.3.2", features = ["serde-1"] }
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
main_error = "0.1.0"
|
main_error = "0.1.0"
|
||||||
meilisearch-core = { path = "../meilisearch-core", version = "0.17.0" }
|
milli = { path = "../milli" }
|
||||||
meilisearch-error = { path = "../meilisearch-error", version = "0.17.0" }
|
|
||||||
meilisearch-schema = { path = "../meilisearch-schema", version = "0.17.0" }
|
|
||||||
meilisearch-tokenizer = {path = "../meilisearch-tokenizer", version = "0.17.0"}
|
|
||||||
mime = "0.3.16"
|
mime = "0.3.16"
|
||||||
once_cell = "1.5.2"
|
once_cell = "1.5.2"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
regex = "1.4.2"
|
regex = "1.4.2"
|
||||||
rustls = "0.18"
|
rustls = "0.18"
|
||||||
serde = { version = "1.0.117", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.59", features = ["preserve_order"] }
|
serde_json = { version = "1.0.59", features = ["preserve_order"] }
|
||||||
serde_qs = "0.8.1"
|
serde_qs = "0.8.1"
|
||||||
sha2 = "0.9.1"
|
sha2 = "0.9.1"
|
||||||
@ -50,37 +44,27 @@ slice-group-by = "0.2.6"
|
|||||||
structopt = "0.3.20"
|
structopt = "0.3.20"
|
||||||
tar = "0.4.29"
|
tar = "0.4.29"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
tokio = { version = "0.2.18", features = ["macros"] }
|
tokio = "*"
|
||||||
ureq = { version = "1.5.1", features = ["tls"], default-features = false }
|
ureq = { version = "1.5.1", default-features = false, features = ["tls"] }
|
||||||
walkdir = "2.3.1"
|
walkdir = "2.3.1"
|
||||||
whoami = "1.0.0"
|
whoami = "1.0.0"
|
||||||
|
meilisearch-error = { path = "../MeiliSearch/meilisearch-error" }
|
||||||
|
|
||||||
[dependencies.sentry]
|
[dependencies.sentry]
|
||||||
version = "0.18.1"
|
|
||||||
default-features = false
|
default-features = false
|
||||||
features = [
|
features = ["with_client_implementation", "with_panic", "with_failure", "with_device_info", "with_rust_info", "with_reqwest_transport", "with_rustls", "with_env_logger"]
|
||||||
"with_client_implementation",
|
|
||||||
"with_panic",
|
|
||||||
"with_failure",
|
|
||||||
"with_device_info",
|
|
||||||
"with_rust_info",
|
|
||||||
"with_reqwest_transport",
|
|
||||||
"with_rustls",
|
|
||||||
"with_env_logger"
|
|
||||||
]
|
|
||||||
optional = true
|
optional = true
|
||||||
|
version = "0.18.1"
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_url_params = "0.2.0"
|
serde_url_params = "0.2.0"
|
||||||
tempdir = "0.3.7"
|
tempdir = "0.3.7"
|
||||||
|
assert-json-diff = { branch = "master", git = "https://github.com/qdequele/assert-json-diff" }
|
||||||
tokio = { version = "0.2.18", features = ["macros", "time"] }
|
tokio = { version = "0.2.18", features = ["macros", "time"] }
|
||||||
|
|
||||||
[dev-dependencies.assert-json-diff]
|
[features]
|
||||||
git = "https://github.com/qdequele/assert-json-diff"
|
default = ["sentry"]
|
||||||
branch = "master"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
vergen = "3.1.0"
|
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
jemallocator = "0.3.2"
|
jemallocator = "0.3.2"
|
||||||
|
109
src/data.rs
109
src/data.rs
@ -3,12 +3,11 @@ 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, Index};
|
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
|
use milli::Index;
|
||||||
|
|
||||||
use crate::error::{Error as MSError, ResponseError};
|
|
||||||
use crate::index_update_callback;
|
|
||||||
use crate::option::Opt;
|
use crate::option::Opt;
|
||||||
|
use crate::updates::UpdateQueue;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
@ -25,7 +24,8 @@ impl Deref for Data {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DataInner {
|
pub struct DataInner {
|
||||||
pub db: Arc<Database>,
|
pub indexes: Arc<Index>,
|
||||||
|
pub update_store: UpdateQueue,
|
||||||
pub db_path: String,
|
pub db_path: String,
|
||||||
pub dumps_dir: PathBuf,
|
pub dumps_dir: PathBuf,
|
||||||
pub dump_batch_size: usize,
|
pub dump_batch_size: usize,
|
||||||
@ -59,104 +59,7 @@ impl ApiKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
pub fn new(opt: Opt) -> Result<Data, Box<dyn Error>> {
|
pub fn new(_opt: Opt) -> Result<Data, Box<dyn Error>> {
|
||||||
let db_path = opt.db_path.clone();
|
todo!()
|
||||||
let dumps_dir = opt.dumps_dir.clone();
|
|
||||||
let dump_batch_size = opt.dump_batch_size;
|
|
||||||
let server_pid = std::process::id();
|
|
||||||
|
|
||||||
let db_opt = DatabaseOptions {
|
|
||||||
main_map_size: opt.max_mdb_size,
|
|
||||||
update_map_size: opt.max_udb_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
let http_payload_size_limit = opt.http_payload_size_limit;
|
|
||||||
|
|
||||||
let db = Arc::new(Database::open_or_create(opt.db_path, db_opt)?);
|
|
||||||
|
|
||||||
let mut api_keys = ApiKeys {
|
|
||||||
master: opt.master_key,
|
|
||||||
private: None,
|
|
||||||
public: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
api_keys.generate_missing_api_keys();
|
|
||||||
|
|
||||||
let inner_data = DataInner {
|
|
||||||
db: db.clone(),
|
|
||||||
db_path,
|
|
||||||
dumps_dir,
|
|
||||||
dump_batch_size,
|
|
||||||
api_keys,
|
|
||||||
server_pid,
|
|
||||||
http_payload_size_limit,
|
|
||||||
};
|
|
||||||
|
|
||||||
let data = Data {
|
|
||||||
inner: Arc::new(inner_data),
|
|
||||||
};
|
|
||||||
|
|
||||||
let callback_context = data.clone();
|
|
||||||
db.set_update_callback(Box::new(move |index_uid, status| {
|
|
||||||
index_update_callback(&index_uid, &callback_context, status);
|
|
||||||
}));
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,6 @@ use actix_web::web;
|
|||||||
use chrono::offset::Utc;
|
use chrono::offset::Utc;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use meilisearch_core::{MainWriter, MainReader, UpdateReader};
|
|
||||||
use meilisearch_core::settings::Settings;
|
|
||||||
use meilisearch_core::update::{apply_settings_update, apply_documents_addition};
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
@ -20,6 +17,7 @@ use crate::Data;
|
|||||||
use crate::error::{Error, ResponseError};
|
use crate::error::{Error, ResponseError};
|
||||||
use crate::helpers::compression;
|
use crate::helpers::compression;
|
||||||
use crate::routes::index;
|
use crate::routes::index;
|
||||||
|
use crate::routes::setting::Settings;
|
||||||
use crate::routes::index::IndexResponse;
|
use crate::routes::index::IndexResponse;
|
||||||
|
|
||||||
// Mutex to share dump progress.
|
// Mutex to share dump progress.
|
||||||
|
25
src/error.rs
25
src/error.rs
@ -6,9 +6,9 @@ use actix_web as aweb;
|
|||||||
use actix_web::error::{JsonPayloadError, QueryPayloadError};
|
use actix_web::error::{JsonPayloadError, QueryPayloadError};
|
||||||
use actix_web::http::StatusCode;
|
use actix_web::http::StatusCode;
|
||||||
use serde::ser::{Serialize, Serializer, SerializeStruct};
|
use serde::ser::{Serialize, Serializer, SerializeStruct};
|
||||||
|
|
||||||
use meilisearch_error::{ErrorCode, Code};
|
use meilisearch_error::{ErrorCode, Code};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ResponseError {
|
pub struct ResponseError {
|
||||||
inner: Box<dyn ErrorCode>,
|
inner: Box<dyn ErrorCode>,
|
||||||
@ -34,18 +34,6 @@ impl From<Error> for ResponseError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<meilisearch_core::Error> for ResponseError {
|
|
||||||
fn from(err: meilisearch_core::Error) -> ResponseError {
|
|
||||||
ResponseError { inner: Box::new(err) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<meilisearch_schema::Error> for ResponseError {
|
|
||||||
fn from(err: meilisearch_schema::Error) -> ResponseError {
|
|
||||||
ResponseError { inner: Box::new(err) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<FacetCountError> for ResponseError {
|
impl From<FacetCountError> for ResponseError {
|
||||||
fn from(err: FacetCountError) -> ResponseError {
|
fn from(err: FacetCountError) -> ResponseError {
|
||||||
ResponseError { inner: Box::new(err) }
|
ResponseError { inner: Box::new(err) }
|
||||||
@ -123,8 +111,9 @@ impl ErrorCode for Error {
|
|||||||
SearchDocuments(_) => Code::SearchDocuments,
|
SearchDocuments(_) => Code::SearchDocuments,
|
||||||
PayloadTooLarge => Code::PayloadTooLarge,
|
PayloadTooLarge => Code::PayloadTooLarge,
|
||||||
UnsupportedMediaType => Code::UnsupportedMediaType,
|
UnsupportedMediaType => Code::UnsupportedMediaType,
|
||||||
DumpAlreadyInProgress => Code::DumpAlreadyInProgress,
|
_ => unreachable!()
|
||||||
DumpProcessFailed(_) => Code::DumpProcessFailed,
|
//DumpAlreadyInProgress => Code::DumpAlreadyInProgress,
|
||||||
|
//DumpProcessFailed(_) => Code::DumpProcessFailed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,12 +259,6 @@ impl From<actix_http::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<meilisearch_core::Error> for Error {
|
|
||||||
fn from(err: meilisearch_core::Error) -> Error {
|
|
||||||
Error::Internal(err.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<serde_json::error::Error> for Error {
|
impl From<serde_json::error::Error> for Error {
|
||||||
fn from(err: serde_json::error::Error) -> Error {
|
fn from(err: serde_json::error::Error) -> Error {
|
||||||
Error::Internal(err.to_string())
|
Error::Internal(err.to_string())
|
||||||
|
55
src/lib.rs
55
src/lib.rs
@ -3,24 +3,20 @@
|
|||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
pub mod models;
|
|
||||||
pub mod option;
|
pub mod option;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
pub mod analytics;
|
mod updates;
|
||||||
pub mod snapshot;
|
//pub mod analytics;
|
||||||
pub mod dump;
|
//pub mod snapshot;
|
||||||
|
//pub mod dump;
|
||||||
|
|
||||||
use actix_http::Error;
|
use actix_http::Error;
|
||||||
use actix_service::ServiceFactory;
|
use actix_service::ServiceFactory;
|
||||||
use actix_web::{dev, web, App};
|
use actix_web::{dev, web, App};
|
||||||
use chrono::Utc;
|
|
||||||
use log::error;
|
|
||||||
|
|
||||||
use meilisearch_core::{Index, MainWriter, ProcessedUpdateResult};
|
|
||||||
|
|
||||||
pub use option::Opt;
|
pub use option::Opt;
|
||||||
pub use self::data::Data;
|
pub use self::data::Data;
|
||||||
use self::error::{payload_error_handler, ResponseError};
|
use self::error::payload_error_handler;
|
||||||
|
|
||||||
pub fn create_app(
|
pub fn create_app(
|
||||||
data: &Data,
|
data: &Data,
|
||||||
@ -55,8 +51,8 @@ pub fn create_app(
|
|||||||
.configure(routes::synonym::services)
|
.configure(routes::synonym::services)
|
||||||
.configure(routes::health::services)
|
.configure(routes::health::services)
|
||||||
.configure(routes::stats::services)
|
.configure(routes::stats::services)
|
||||||
.configure(routes::key::services)
|
.configure(routes::key::services);
|
||||||
.configure(routes::dump::services);
|
//.configure(routes::dump::services);
|
||||||
if enable_frontend {
|
if enable_frontend {
|
||||||
app
|
app
|
||||||
.service(routes::load_html)
|
.service(routes::load_html)
|
||||||
@ -65,40 +61,3 @@ pub fn create_app(
|
|||||||
app
|
app
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index_update_callback_txn(index: Index, index_uid: &str, data: &Data, mut writer: &mut MainWriter) -> Result<(), String> {
|
|
||||||
if let Err(e) = data.db.compute_stats(&mut writer, index_uid) {
|
|
||||||
return Err(format!("Impossible to compute stats; {}", e));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(e) = data.db.set_last_update(&mut writer, &Utc::now()) {
|
|
||||||
return Err(format!("Impossible to update last_update; {}", e));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(e) = index.main.put_updated_at(&mut writer) {
|
|
||||||
return Err(format!("Impossible to update updated_at; {}", e));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) {
|
|
||||||
if status.error.is_some() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(index) = data.db.open_index(index_uid) {
|
|
||||||
let db = &data.db;
|
|
||||||
let res = db.main_write::<_, _, ResponseError>(|mut writer| {
|
|
||||||
if let Err(e) = index_update_callback_txn(index, index_uid, data, &mut writer) {
|
|
||||||
error!("{}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
match res {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => error!("{}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
41
src/main.rs
41
src/main.rs
@ -1,14 +1,13 @@
|
|||||||
use std::{env, thread};
|
use std::env;
|
||||||
|
|
||||||
use actix_cors::Cors;
|
use actix_cors::Cors;
|
||||||
use actix_web::{middleware, HttpServer};
|
use actix_web::{middleware, HttpServer};
|
||||||
use main_error::MainError;
|
use main_error::MainError;
|
||||||
use meilisearch_http::helpers::NormalizePath;
|
use meilisearch_http::helpers::NormalizePath;
|
||||||
use meilisearch_http::{create_app, index_update_callback, Data, Opt};
|
use meilisearch_http::{create_app, Data, Opt};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use meilisearch_http::{snapshot, dump};
|
|
||||||
|
|
||||||
mod analytics;
|
//mod analytics;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
@ -52,31 +51,25 @@ async fn main() -> Result<(), MainError> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(path) = &opt.import_snapshot {
|
//if let Some(path) = &opt.import_snapshot {
|
||||||
snapshot::load_snapshot(&opt.db_path, path, opt.ignore_snapshot_if_db_exists, opt.ignore_missing_snapshot)?;
|
//snapshot::load_snapshot(&opt.db_path, path, opt.ignore_snapshot_if_db_exists, opt.ignore_missing_snapshot)?;
|
||||||
}
|
//}
|
||||||
|
|
||||||
let data = Data::new(opt.clone())?;
|
let data = Data::new(opt.clone())?;
|
||||||
|
|
||||||
if !opt.no_analytics {
|
//if !opt.no_analytics {
|
||||||
let analytics_data = data.clone();
|
//let analytics_data = data.clone();
|
||||||
let analytics_opt = opt.clone();
|
//let analytics_opt = opt.clone();
|
||||||
thread::spawn(move || analytics::analytics_sender(analytics_data, analytics_opt));
|
//thread::spawn(move || analytics::analytics_sender(analytics_data, analytics_opt));
|
||||||
}
|
//}
|
||||||
|
|
||||||
let data_cloned = data.clone();
|
//if let Some(path) = &opt.import_dump {
|
||||||
data.db.set_update_callback(Box::new(move |name, status| {
|
//dump::import_dump(&data, path, opt.dump_batch_size)?;
|
||||||
index_update_callback(name, &data_cloned, status);
|
//}
|
||||||
}));
|
|
||||||
|
|
||||||
|
//if opt.schedule_snapshot {
|
||||||
if let Some(path) = &opt.import_dump {
|
//snapshot::schedule_snapshot(data.clone(), &opt.snapshot_dir, opt.snapshot_interval_sec.unwrap_or(86400))?;
|
||||||
dump::import_dump(&data, path, opt.dump_batch_size)?;
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
if opt.schedule_snapshot {
|
|
||||||
snapshot::schedule_snapshot(data.clone(), &opt.snapshot_dir, opt.snapshot_interval_sec.unwrap_or(86400))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_launch_resume(&opt, &data);
|
print_launch_resume(&opt, &data);
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ use std::io::{BufReader, Read};
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use byte_unit::Byte;
|
||||||
use rustls::internal::pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
|
use rustls::internal::pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
|
||||||
use rustls::{
|
use rustls::{
|
||||||
AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, NoClientAuth,
|
AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, NoClientAuth,
|
||||||
@ -12,7 +13,7 @@ use structopt::StructOpt;
|
|||||||
|
|
||||||
const POSSIBLE_ENV: [&str; 2] = ["development", "production"];
|
const POSSIBLE_ENV: [&str; 2] = ["development", "production"];
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, StructOpt)]
|
#[derive(Debug, Clone, StructOpt)]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
/// The destination where the database must be created.
|
/// The destination where the database must be created.
|
||||||
#[structopt(long, env = "MEILI_DB_PATH", default_value = "./data.ms")]
|
#[structopt(long, env = "MEILI_DB_PATH", default_value = "./data.ms")]
|
||||||
@ -49,16 +50,16 @@ pub struct Opt {
|
|||||||
pub no_analytics: bool,
|
pub no_analytics: bool,
|
||||||
|
|
||||||
/// The maximum size, in bytes, of the main lmdb database directory
|
/// The maximum size, in bytes, of the main lmdb database directory
|
||||||
#[structopt(long, env = "MEILI_MAX_MDB_SIZE", default_value = "107374182400")] // 100GB
|
#[structopt(long, env = "MEILI_MAX_MDB_SIZE", default_value = "100 GiB")]
|
||||||
pub max_mdb_size: usize,
|
pub max_mdb_size: Byte,
|
||||||
|
|
||||||
/// The maximum size, in bytes, of the update lmdb database directory
|
/// The maximum size, in bytes, of the update lmdb database directory
|
||||||
#[structopt(long, env = "MEILI_MAX_UDB_SIZE", default_value = "107374182400")] // 100GB
|
#[structopt(long, env = "MEILI_MAX_UDB_SIZE", default_value = "10 GiB")]
|
||||||
pub max_udb_size: usize,
|
pub max_udb_size: Byte,
|
||||||
|
|
||||||
/// The maximum size, in bytes, of accepted JSON payloads
|
/// The maximum size, in bytes, of accepted JSON payloads
|
||||||
#[structopt(long, env = "MEILI_HTTP_PAYLOAD_SIZE_LIMIT", default_value = "10485760")] // 10MB
|
#[structopt(long, env = "MEILI_HTTP_PAYLOAD_SIZE_LIMIT", default_value = "10 MiB")]
|
||||||
pub http_payload_size_limit: usize,
|
pub http_payload_size_limit: Byte,
|
||||||
|
|
||||||
/// Read server certificates from CERTFILE.
|
/// Read server certificates from CERTFILE.
|
||||||
/// This should contain PEM-format certificates
|
/// This should contain PEM-format certificates
|
||||||
|
@ -1,23 +1,20 @@
|
|||||||
use std::collections::{BTreeSet, HashSet};
|
|
||||||
|
|
||||||
use actix_web::{delete, get, post, put};
|
use actix_web::{delete, get, post, put};
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use meilisearch_core::{update, MainReader};
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
use crate::error::{Error, ResponseError};
|
use crate::error::ResponseError;
|
||||||
use crate::helpers::Authentication;
|
use crate::helpers::Authentication;
|
||||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
use crate::routes::IndexParam;
|
||||||
|
|
||||||
type Document = IndexMap<String, Value>;
|
type Document = IndexMap<String, Value>;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct DocumentParam {
|
struct DocumentParam {
|
||||||
index_uid: String,
|
_index_uid: String,
|
||||||
document_id: String,
|
_document_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
@ -35,8 +32,8 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
|||||||
wrap = "Authentication::Public"
|
wrap = "Authentication::Public"
|
||||||
)]
|
)]
|
||||||
async fn get_document(
|
async fn get_document(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<DocumentParam>,
|
_path: web::Path<DocumentParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -46,8 +43,8 @@ async fn get_document(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete_document(
|
async fn delete_document(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<DocumentParam>,
|
_path: web::Path<DocumentParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -55,62 +52,51 @@ async fn delete_document(
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||||
struct BrowseQuery {
|
struct BrowseQuery {
|
||||||
offset: Option<usize>,
|
_offset: Option<usize>,
|
||||||
limit: Option<usize>,
|
_limit: Option<usize>,
|
||||||
attributes_to_retrieve: Option<String>,
|
_attributes_to_retrieve: Option<String>,
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_all_documents_sync(
|
|
||||||
data: &web::Data<Data>,
|
|
||||||
reader: &MainReader,
|
|
||||||
index_uid: &str,
|
|
||||||
offset: usize,
|
|
||||||
limit: usize,
|
|
||||||
attributes_to_retrieve: Option<&String>
|
|
||||||
) -> Result<Vec<Document>, Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/indexes/{index_uid}/documents", wrap = "Authentication::Public")]
|
#[get("/indexes/{index_uid}/documents", wrap = "Authentication::Public")]
|
||||||
async fn get_all_documents(
|
async fn get_all_documents(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
params: web::Query<BrowseQuery>,
|
_params: web::Query<BrowseQuery>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_primary_key(document: &IndexMap<String, Value>) -> Option<String> {
|
//fn find_primary_key(document: &IndexMap<String, Value>) -> Option<String> {
|
||||||
for key in document.keys() {
|
//for key in document.keys() {
|
||||||
if key.to_lowercase().contains("id") {
|
//if key.to_lowercase().contains("id") {
|
||||||
return Some(key.to_string());
|
//return Some(key.to_string());
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
None
|
//None
|
||||||
}
|
//}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||||
struct UpdateDocumentsQuery {
|
struct UpdateDocumentsQuery {
|
||||||
primary_key: Option<String>,
|
_primary_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_multiple_documents(
|
async fn update_multiple_documents(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
params: web::Query<UpdateDocumentsQuery>,
|
_params: web::Query<UpdateDocumentsQuery>,
|
||||||
body: web::Json<Vec<Document>>,
|
_body: web::Json<Vec<Document>>,
|
||||||
is_partial: bool,
|
_is_partial: bool,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
#[post("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||||
async fn add_documents(
|
async fn add_documents(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
params: web::Query<UpdateDocumentsQuery>,
|
_params: web::Query<UpdateDocumentsQuery>,
|
||||||
body: web::Json<Vec<Document>>,
|
_body: web::Json<Vec<Document>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -130,17 +116,17 @@ async fn update_documents(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete_documents(
|
async fn delete_documents(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
body: web::Json<Vec<Value>>,
|
_body: web::Json<Vec<Value>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
#[delete("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||||
async fn clear_all_documents(
|
async fn clear_all_documents(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
use actix_web::{delete, get, post, put};
|
use actix_web::{delete, get, post, put};
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use log::error;
|
|
||||||
use meilisearch_core::{Database, MainReader, UpdateReader};
|
|
||||||
use meilisearch_core::update::UpdateStatus;
|
|
||||||
use rand::seq::SliceRandom;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
use crate::error::{Error, ResponseError};
|
use crate::error::ResponseError;
|
||||||
use crate::helpers::Authentication;
|
use crate::helpers::Authentication;
|
||||||
use crate::routes::IndexParam;
|
use crate::routes::IndexParam;
|
||||||
|
|
||||||
@ -22,10 +18,6 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
|||||||
.service(get_all_updates_status);
|
.service(get_all_updates_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_uid() -> String {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct IndexResponse {
|
pub struct IndexResponse {
|
||||||
@ -36,22 +28,15 @@ pub struct IndexResponse {
|
|||||||
pub primary_key: Option<String>,
|
pub primary_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_indexes_sync(data: &web::Data<Data>, reader: &MainReader) -> Result<Vec<IndexResponse>, ResponseError> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/indexes", wrap = "Authentication::Private")]
|
#[get("/indexes", wrap = "Authentication::Private")]
|
||||||
async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
async fn list_indexes(_data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||||
let reader = data.db.main_read_txn()?;
|
todo!()
|
||||||
let indexes = list_indexes_sync(&data, &reader)?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(indexes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
#[get("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||||
async fn get_index(
|
async fn get_index(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -64,20 +49,10 @@ struct IndexCreateRequest {
|
|||||||
primary_key: Option<String>,
|
primary_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn create_index_sync(
|
|
||||||
database: &std::sync::Arc<Database>,
|
|
||||||
uid: String,
|
|
||||||
name: String,
|
|
||||||
primary_key: Option<String>,
|
|
||||||
) -> Result<IndexResponse, Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/indexes", wrap = "Authentication::Private")]
|
#[post("/indexes", wrap = "Authentication::Private")]
|
||||||
async fn create_index(
|
async fn create_index(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
body: web::Json<IndexCreateRequest>,
|
_body: web::Json<IndexCreateRequest>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -101,25 +76,25 @@ struct UpdateIndexResponse {
|
|||||||
|
|
||||||
#[put("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
#[put("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||||
async fn update_index(
|
async fn update_index(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
body: web::Json<IndexCreateRequest>,
|
_body: web::Json<IndexCreateRequest>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
#[delete("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||||
async fn delete_index(
|
async fn delete_index(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct UpdateParam {
|
struct UpdateParam {
|
||||||
index_uid: String,
|
_index_uid: String,
|
||||||
update_id: u64,
|
_update_id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get(
|
#[get(
|
||||||
@ -127,23 +102,16 @@ struct UpdateParam {
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get_update_status(
|
async fn get_update_status(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<UpdateParam>,
|
_path: web::Path<UpdateParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
pub fn get_all_updates_status_sync(
|
|
||||||
data: &web::Data<Data>,
|
|
||||||
reader: &UpdateReader,
|
|
||||||
index_uid: &str,
|
|
||||||
) -> Result<Vec<UpdateStatus>, Error> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/indexes/{index_uid}/updates", wrap = "Authentication::Private")]
|
#[get("/indexes/{index_uid}/updates", wrap = "Authentication::Private")]
|
||||||
async fn get_all_updates_status(
|
async fn get_all_updates_status(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ struct KeysResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/keys", wrap = "Authentication::Admin")]
|
#[get("/keys", wrap = "Authentication::Admin")]
|
||||||
async fn list(data: web::Data<Data>) -> HttpResponse {
|
async fn list(_data: web::Data<Data>) -> HttpResponse {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ pub mod setting;
|
|||||||
pub mod stats;
|
pub mod stats;
|
||||||
pub mod stop_words;
|
pub mod stop_words;
|
||||||
pub mod synonym;
|
pub mod synonym;
|
||||||
pub mod dump;
|
//pub mod dump;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct IndexParam {
|
pub struct IndexParam {
|
||||||
index_uid: String,
|
_index_uid: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
|
|
||||||
use actix_web::{get, post, web, HttpResponse};
|
use actix_web::{get, post, web, HttpResponse};
|
||||||
use log::warn;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::error::{Error, FacetCountError, ResponseError};
|
use crate::error::ResponseError;
|
||||||
use crate::helpers::meilisearch::{IndexSearchExt, SearchResult};
|
|
||||||
use crate::helpers::Authentication;
|
use crate::helpers::Authentication;
|
||||||
use crate::routes::IndexParam;
|
use crate::routes::IndexParam;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
|
||||||
use meilisearch_core::facets::FacetFilter;
|
|
||||||
use meilisearch_schema::{FieldId, Schema};
|
|
||||||
|
|
||||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(search_with_post).service(search_with_url_query);
|
cfg.service(search_with_post).service(search_with_url_query);
|
||||||
}
|
}
|
||||||
@ -36,9 +29,9 @@ pub struct SearchQuery {
|
|||||||
|
|
||||||
#[get("/indexes/{index_uid}/search", wrap = "Authentication::Public")]
|
#[get("/indexes/{index_uid}/search", wrap = "Authentication::Public")]
|
||||||
async fn search_with_url_query(
|
async fn search_with_url_query(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
params: web::Query<SearchQuery>,
|
_params: web::Query<SearchQuery>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -46,53 +39,24 @@ async fn search_with_url_query(
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||||
pub struct SearchQueryPost {
|
pub struct SearchQueryPost {
|
||||||
q: Option<String>,
|
_q: Option<String>,
|
||||||
offset: Option<usize>,
|
_offset: Option<usize>,
|
||||||
limit: Option<usize>,
|
_limit: Option<usize>,
|
||||||
attributes_to_retrieve: Option<Vec<String>>,
|
_attributes_to_retrieve: Option<Vec<String>>,
|
||||||
attributes_to_crop: Option<Vec<String>>,
|
_attributes_to_crop: Option<Vec<String>>,
|
||||||
crop_length: Option<usize>,
|
_crop_length: Option<usize>,
|
||||||
attributes_to_highlight: Option<Vec<String>>,
|
_attributes_to_highlight: Option<Vec<String>>,
|
||||||
filters: Option<String>,
|
_filters: Option<String>,
|
||||||
matches: Option<bool>,
|
_matches: Option<bool>,
|
||||||
facet_filters: Option<Value>,
|
_facet_filters: Option<Value>,
|
||||||
facets_distribution: Option<Vec<String>>,
|
_facets_distribution: Option<Vec<String>>,
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SearchQueryPost> for SearchQuery {
|
|
||||||
fn from(other: SearchQueryPost) -> SearchQuery {
|
|
||||||
SearchQuery {
|
|
||||||
q: other.q,
|
|
||||||
offset: other.offset,
|
|
||||||
limit: other.limit,
|
|
||||||
attributes_to_retrieve: other.attributes_to_retrieve.map(|attrs| attrs.join(",")),
|
|
||||||
attributes_to_crop: other.attributes_to_crop.map(|attrs| attrs.join(",")),
|
|
||||||
crop_length: other.crop_length,
|
|
||||||
attributes_to_highlight: other.attributes_to_highlight.map(|attrs| attrs.join(",")),
|
|
||||||
filters: other.filters,
|
|
||||||
matches: other.matches,
|
|
||||||
facet_filters: other.facet_filters.map(|f| f.to_string()),
|
|
||||||
facets_distribution: other.facets_distribution.map(|f| format!("{:?}", f)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/indexes/{index_uid}/search", wrap = "Authentication::Public")]
|
#[post("/indexes/{index_uid}/search", wrap = "Authentication::Public")]
|
||||||
async fn search_with_post(
|
async fn search_with_post(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
params: web::Json<SearchQueryPost>,
|
_params: web::Json<SearchQueryPost>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let query: SearchQuery = params.0.into();
|
|
||||||
let search_result = query.search(&path.index_uid, data)?;
|
|
||||||
Ok(HttpResponse::Ok().json(search_result))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SearchQuery {
|
|
||||||
fn search(
|
|
||||||
&self,
|
|
||||||
index_uid: &str,
|
|
||||||
data: web::Data<Data>,
|
|
||||||
) -> Result<SearchResult, ResponseError> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use actix_web::{delete, get, post};
|
use actix_web::{delete, get, post};
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use meilisearch_core::{MainReader, UpdateWriter};
|
|
||||||
use meilisearch_core::settings::{Settings, SettingsUpdate, UpdateState, DEFAULT_RANKING_RULES};
|
|
||||||
use meilisearch_schema::Schema;
|
|
||||||
|
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
use crate::error::{Error, ResponseError};
|
use crate::error::ResponseError;
|
||||||
use crate::helpers::Authentication;
|
use crate::helpers::Authentication;
|
||||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
use crate::updates::Settings;
|
||||||
|
|
||||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.service(update_all)
|
cfg.service(update_all)
|
||||||
@ -32,27 +29,28 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
|||||||
.service(update_attributes_for_faceting);
|
.service(update_attributes_for_faceting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[post("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
#[post("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||||
async fn update_all(
|
async fn update_all(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
body: web::Json<Settings>,
|
_body: web::Json<Settings>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
#[get("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||||
async fn get_all(
|
async fn get_all(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
#[delete("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||||
async fn delete_all(
|
async fn delete_all(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -62,8 +60,8 @@ async fn delete_all(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get_rules(
|
async fn get_rules(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -73,9 +71,9 @@ async fn get_rules(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn update_rules(
|
async fn update_rules(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
body: web::Json<Option<Vec<String>>>,
|
_body: web::Json<Option<Vec<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -85,8 +83,8 @@ async fn update_rules(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete_rules(
|
async fn delete_rules(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -96,8 +94,8 @@ async fn delete_rules(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get_distinct(
|
async fn get_distinct(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -107,9 +105,9 @@ async fn get_distinct(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn update_distinct(
|
async fn update_distinct(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
body: web::Json<Option<String>>,
|
_body: web::Json<Option<String>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -119,8 +117,8 @@ async fn update_distinct(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete_distinct(
|
async fn delete_distinct(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -130,8 +128,8 @@ async fn delete_distinct(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get_searchable(
|
async fn get_searchable(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -141,9 +139,9 @@ async fn get_searchable(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn update_searchable(
|
async fn update_searchable(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
body: web::Json<Option<Vec<String>>>,
|
_body: web::Json<Option<Vec<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -153,8 +151,8 @@ async fn update_searchable(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete_searchable(
|
async fn delete_searchable(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -164,8 +162,8 @@ async fn delete_searchable(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get_displayed(
|
async fn get_displayed(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -175,9 +173,9 @@ async fn get_displayed(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn update_displayed(
|
async fn update_displayed(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
body: web::Json<Option<BTreeSet<String>>>,
|
_body: web::Json<Option<BTreeSet<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -187,8 +185,8 @@ async fn update_displayed(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete_displayed(
|
async fn delete_displayed(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -198,8 +196,8 @@ async fn delete_displayed(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get_attributes_for_faceting(
|
async fn get_attributes_for_faceting(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -209,9 +207,9 @@ async fn get_attributes_for_faceting(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn update_attributes_for_faceting(
|
async fn update_attributes_for_faceting(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
body: web::Json<Option<Vec<String>>>,
|
_body: web::Json<Option<Vec<String>>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -221,8 +219,8 @@ async fn update_attributes_for_faceting(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete_attributes_for_faceting(
|
async fn delete_attributes_for_faceting(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<String>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,9 @@ use actix_web::web;
|
|||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
use actix_web::get;
|
use actix_web::get;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use log::error;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use walkdir::WalkDir;
|
|
||||||
|
|
||||||
use crate::error::{Error, ResponseError};
|
use crate::error::ResponseError;
|
||||||
use crate::helpers::Authentication;
|
use crate::helpers::Authentication;
|
||||||
use crate::routes::IndexParam;
|
use crate::routes::IndexParam;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
@ -29,8 +27,8 @@ struct IndexStatsResponse {
|
|||||||
|
|
||||||
#[get("/indexes/{index_uid}/stats", wrap = "Authentication::Private")]
|
#[get("/indexes/{index_uid}/stats", wrap = "Authentication::Private")]
|
||||||
async fn index_stats(
|
async fn index_stats(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -44,7 +42,7 @@ struct StatsResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/stats", wrap = "Authentication::Private")]
|
#[get("/stats", wrap = "Authentication::Private")]
|
||||||
async fn get_stats(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
async fn get_stats(_data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use actix_web::{delete, get, post};
|
use actix_web::{delete, get, post};
|
||||||
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use crate::error::{Error, ResponseError};
|
use crate::error::ResponseError;
|
||||||
use crate::helpers::Authentication;
|
use crate::helpers::Authentication;
|
||||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
use crate::routes::IndexParam;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
|
||||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
@ -17,8 +16,8 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get(
|
async fn get(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -28,9 +27,9 @@ async fn get(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn update(
|
async fn update(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
body: web::Json<BTreeSet<String>>,
|
_body: web::Json<BTreeSet<String>>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -40,8 +39,8 @@ async fn update(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete(
|
async fn delete(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,10 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use actix_web::{delete, get, post};
|
use actix_web::{delete, get, post};
|
||||||
use indexmap::IndexMap;
|
|
||||||
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
|
|
||||||
|
|
||||||
use crate::error::{Error, ResponseError};
|
use crate::error::ResponseError;
|
||||||
use crate::helpers::Authentication;
|
use crate::helpers::Authentication;
|
||||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
use crate::routes::IndexParam;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
|
||||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
@ -19,8 +17,8 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn get(
|
async fn get(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -30,9 +28,9 @@ async fn get(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn update(
|
async fn update(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
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> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
@ -42,8 +40,8 @@ async fn update(
|
|||||||
wrap = "Authentication::Private"
|
wrap = "Authentication::Private"
|
||||||
)]
|
)]
|
||||||
async fn delete(
|
async fn delete(
|
||||||
data: web::Data<Data>,
|
_data: web::Data<Data>,
|
||||||
path: web::Path<IndexParam>,
|
_path: web::Path<IndexParam>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
17
src/updates/mod.rs
Normal file
17
src/updates/mod.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
mod settings;
|
||||||
|
|
||||||
|
pub use settings::{Settings, Facets};
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
enum UpdateMeta {
|
||||||
|
DocumentsAddition { method: String, format: String },
|
||||||
|
ClearDocuments,
|
||||||
|
Settings(Settings),
|
||||||
|
Facets(Facets),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct UpdateQueue;
|
51
src/updates/settings.rs
Normal file
51
src/updates/settings.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use std::num::NonZeroUsize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize, de::Deserializer};
|
||||||
|
|
||||||
|
// Any value that is present is considered Some value, including null.
|
||||||
|
fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
|
||||||
|
where T: Deserialize<'de>,
|
||||||
|
D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
Deserialize::deserialize(deserializer).map(Some)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Settings {
|
||||||
|
#[serde(
|
||||||
|
default,
|
||||||
|
deserialize_with = "deserialize_some",
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
)]
|
||||||
|
displayed_attributes: Option<Option<Vec<String>>>,
|
||||||
|
|
||||||
|
#[serde(
|
||||||
|
default,
|
||||||
|
deserialize_with = "deserialize_some",
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
)]
|
||||||
|
searchable_attributes: Option<Option<Vec<String>>>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
faceted_attributes: Option<HashMap<String, String>>,
|
||||||
|
|
||||||
|
#[serde(
|
||||||
|
default,
|
||||||
|
deserialize_with = "deserialize_some",
|
||||||
|
skip_serializing_if = "Option::is_none",
|
||||||
|
)]
|
||||||
|
criteria: Option<Option<Vec<String>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Facets {
|
||||||
|
level_group_size: Option<NonZeroUsize>,
|
||||||
|
min_level_size: Option<NonZeroUsize>,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user