mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-25 19:45:05 +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]
|
||||
name = "meilisearch-http"
|
||||
authors = ["Quentin de Quelen <quentin@dequelen.me>", "Clément Renault <clement@meilisearch.com>"]
|
||||
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"
|
||||
|
||||
license = "MIT"
|
||||
name = "meilisearch-http"
|
||||
version = "0.17.0"
|
||||
[[bin]]
|
||||
name = "meilisearch"
|
||||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
default = ["sentry"]
|
||||
[build-dependencies]
|
||||
vergen = "3.1.0"
|
||||
|
||||
[dependencies]
|
||||
actix-cors = "0.5.3"
|
||||
@ -22,6 +18,7 @@ actix-http = "2"
|
||||
actix-rt = "1"
|
||||
actix-service = "1.0.6"
|
||||
actix-web = { version = "3.3.2", features = ["rustls"] }
|
||||
byte-unit = { version = "4.0.9", default-features = false, features = ["std"] }
|
||||
bytes = "0.6.0"
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
crossbeam-channel = "0.5.0"
|
||||
@ -29,19 +26,16 @@ env_logger = "0.8.2"
|
||||
flate2 = "1.0.18"
|
||||
futures = "0.3.7"
|
||||
http = "0.2.1"
|
||||
indexmap = { version = "1.3.2", features = ["serde-1"] }
|
||||
indexmap = { version = "1.3.2", features = ["serde-1"] }
|
||||
log = "0.4.8"
|
||||
main_error = "0.1.0"
|
||||
meilisearch-core = { path = "../meilisearch-core", version = "0.17.0" }
|
||||
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"}
|
||||
milli = { path = "../milli" }
|
||||
mime = "0.3.16"
|
||||
once_cell = "1.5.2"
|
||||
rand = "0.7.3"
|
||||
regex = "1.4.2"
|
||||
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_qs = "0.8.1"
|
||||
sha2 = "0.9.1"
|
||||
@ -50,37 +44,27 @@ slice-group-by = "0.2.6"
|
||||
structopt = "0.3.20"
|
||||
tar = "0.4.29"
|
||||
tempfile = "3.1.0"
|
||||
tokio = { version = "0.2.18", features = ["macros"] }
|
||||
ureq = { version = "1.5.1", features = ["tls"], default-features = false }
|
||||
tokio = "*"
|
||||
ureq = { version = "1.5.1", default-features = false, features = ["tls"] }
|
||||
walkdir = "2.3.1"
|
||||
whoami = "1.0.0"
|
||||
meilisearch-error = { path = "../MeiliSearch/meilisearch-error" }
|
||||
|
||||
[dependencies.sentry]
|
||||
version = "0.18.1"
|
||||
default-features = false
|
||||
features = [
|
||||
"with_client_implementation",
|
||||
"with_panic",
|
||||
"with_failure",
|
||||
"with_device_info",
|
||||
"with_rust_info",
|
||||
"with_reqwest_transport",
|
||||
"with_rustls",
|
||||
"with_env_logger"
|
||||
]
|
||||
features = ["with_client_implementation", "with_panic", "with_failure", "with_device_info", "with_rust_info", "with_reqwest_transport", "with_rustls", "with_env_logger"]
|
||||
optional = true
|
||||
version = "0.18.1"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
serde_url_params = "0.2.0"
|
||||
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"] }
|
||||
|
||||
[dev-dependencies.assert-json-diff]
|
||||
git = "https://github.com/qdequele/assert-json-diff"
|
||||
branch = "master"
|
||||
|
||||
[build-dependencies]
|
||||
vergen = "3.1.0"
|
||||
[features]
|
||||
default = ["sentry"]
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
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::sync::Arc;
|
||||
|
||||
use meilisearch_core::{Database, DatabaseOptions, Index};
|
||||
use sha2::Digest;
|
||||
use milli::Index;
|
||||
|
||||
use crate::error::{Error as MSError, ResponseError};
|
||||
use crate::index_update_callback;
|
||||
use crate::option::Opt;
|
||||
use crate::updates::UpdateQueue;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Data {
|
||||
@ -25,7 +24,8 @@ impl Deref for Data {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DataInner {
|
||||
pub db: Arc<Database>,
|
||||
pub indexes: Arc<Index>,
|
||||
pub update_store: UpdateQueue,
|
||||
pub db_path: String,
|
||||
pub dumps_dir: PathBuf,
|
||||
pub dump_batch_size: usize,
|
||||
@ -59,104 +59,7 @@ impl ApiKeys {
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn new(opt: Opt) -> Result<Data, Box<dyn Error>> {
|
||||
let db_path = opt.db_path.clone();
|
||||
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)
|
||||
}
|
||||
}
|
||||
pub fn new(_opt: Opt) -> Result<Data, Box<dyn Error>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,6 @@ use actix_web::web;
|
||||
use chrono::offset::Utc;
|
||||
use indexmap::IndexMap;
|
||||
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 serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
@ -20,6 +17,7 @@ use crate::Data;
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::compression;
|
||||
use crate::routes::index;
|
||||
use crate::routes::setting::Settings;
|
||||
use crate::routes::index::IndexResponse;
|
||||
|
||||
// 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::http::StatusCode;
|
||||
use serde::ser::{Serialize, Serializer, SerializeStruct};
|
||||
|
||||
use meilisearch_error::{ErrorCode, Code};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ResponseError {
|
||||
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 {
|
||||
fn from(err: FacetCountError) -> ResponseError {
|
||||
ResponseError { inner: Box::new(err) }
|
||||
@ -123,8 +111,9 @@ impl ErrorCode for Error {
|
||||
SearchDocuments(_) => Code::SearchDocuments,
|
||||
PayloadTooLarge => Code::PayloadTooLarge,
|
||||
UnsupportedMediaType => Code::UnsupportedMediaType,
|
||||
DumpAlreadyInProgress => Code::DumpAlreadyInProgress,
|
||||
DumpProcessFailed(_) => Code::DumpProcessFailed,
|
||||
_ => unreachable!()
|
||||
//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 {
|
||||
fn from(err: serde_json::error::Error) -> Error {
|
||||
Error::Internal(err.to_string())
|
||||
|
55
src/lib.rs
55
src/lib.rs
@ -3,24 +3,20 @@
|
||||
pub mod data;
|
||||
pub mod error;
|
||||
pub mod helpers;
|
||||
pub mod models;
|
||||
pub mod option;
|
||||
pub mod routes;
|
||||
pub mod analytics;
|
||||
pub mod snapshot;
|
||||
pub mod dump;
|
||||
mod updates;
|
||||
//pub mod analytics;
|
||||
//pub mod snapshot;
|
||||
//pub mod dump;
|
||||
|
||||
use actix_http::Error;
|
||||
use actix_service::ServiceFactory;
|
||||
use actix_web::{dev, web, App};
|
||||
use chrono::Utc;
|
||||
use log::error;
|
||||
|
||||
use meilisearch_core::{Index, MainWriter, ProcessedUpdateResult};
|
||||
|
||||
pub use option::Opt;
|
||||
pub use self::data::Data;
|
||||
use self::error::{payload_error_handler, ResponseError};
|
||||
use self::error::payload_error_handler;
|
||||
|
||||
pub fn create_app(
|
||||
data: &Data,
|
||||
@ -55,8 +51,8 @@ pub fn create_app(
|
||||
.configure(routes::synonym::services)
|
||||
.configure(routes::health::services)
|
||||
.configure(routes::stats::services)
|
||||
.configure(routes::key::services)
|
||||
.configure(routes::dump::services);
|
||||
.configure(routes::key::services);
|
||||
//.configure(routes::dump::services);
|
||||
if enable_frontend {
|
||||
app
|
||||
.service(routes::load_html)
|
||||
@ -65,40 +61,3 @@ pub fn create_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_web::{middleware, HttpServer};
|
||||
use main_error::MainError;
|
||||
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 meilisearch_http::{snapshot, dump};
|
||||
|
||||
mod analytics;
|
||||
//mod analytics;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[global_allocator]
|
||||
@ -52,31 +51,25 @@ async fn main() -> Result<(), MainError> {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
if let Some(path) = &opt.import_snapshot {
|
||||
snapshot::load_snapshot(&opt.db_path, path, opt.ignore_snapshot_if_db_exists, opt.ignore_missing_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)?;
|
||||
//}
|
||||
|
||||
let data = Data::new(opt.clone())?;
|
||||
|
||||
if !opt.no_analytics {
|
||||
let analytics_data = data.clone();
|
||||
let analytics_opt = opt.clone();
|
||||
thread::spawn(move || analytics::analytics_sender(analytics_data, analytics_opt));
|
||||
}
|
||||
//if !opt.no_analytics {
|
||||
//let analytics_data = data.clone();
|
||||
//let analytics_opt = opt.clone();
|
||||
//thread::spawn(move || analytics::analytics_sender(analytics_data, analytics_opt));
|
||||
//}
|
||||
|
||||
let data_cloned = data.clone();
|
||||
data.db.set_update_callback(Box::new(move |name, status| {
|
||||
index_update_callback(name, &data_cloned, status);
|
||||
}));
|
||||
//if let Some(path) = &opt.import_dump {
|
||||
//dump::import_dump(&data, path, opt.dump_batch_size)?;
|
||||
//}
|
||||
|
||||
|
||||
if let Some(path) = &opt.import_dump {
|
||||
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))?;
|
||||
}
|
||||
//if opt.schedule_snapshot {
|
||||
//snapshot::schedule_snapshot(data.clone(), &opt.snapshot_dir, opt.snapshot_interval_sec.unwrap_or(86400))?;
|
||||
//}
|
||||
|
||||
print_launch_resume(&opt, &data);
|
||||
|
||||
|
@ -3,6 +3,7 @@ use std::io::{BufReader, Read};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use byte_unit::Byte;
|
||||
use rustls::internal::pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
|
||||
use rustls::{
|
||||
AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, NoClientAuth,
|
||||
@ -12,7 +13,7 @@ use structopt::StructOpt;
|
||||
|
||||
const POSSIBLE_ENV: [&str; 2] = ["development", "production"];
|
||||
|
||||
#[derive(Debug, Default, Clone, StructOpt)]
|
||||
#[derive(Debug, Clone, StructOpt)]
|
||||
pub struct Opt {
|
||||
/// The destination where the database must be created.
|
||||
#[structopt(long, env = "MEILI_DB_PATH", default_value = "./data.ms")]
|
||||
@ -49,16 +50,16 @@ pub struct Opt {
|
||||
pub no_analytics: bool,
|
||||
|
||||
/// The maximum size, in bytes, of the main lmdb database directory
|
||||
#[structopt(long, env = "MEILI_MAX_MDB_SIZE", default_value = "107374182400")] // 100GB
|
||||
pub max_mdb_size: usize,
|
||||
#[structopt(long, env = "MEILI_MAX_MDB_SIZE", default_value = "100 GiB")]
|
||||
pub max_mdb_size: Byte,
|
||||
|
||||
/// The maximum size, in bytes, of the update lmdb database directory
|
||||
#[structopt(long, env = "MEILI_MAX_UDB_SIZE", default_value = "107374182400")] // 100GB
|
||||
pub max_udb_size: usize,
|
||||
#[structopt(long, env = "MEILI_MAX_UDB_SIZE", default_value = "10 GiB")]
|
||||
pub max_udb_size: Byte,
|
||||
|
||||
/// The maximum size, in bytes, of accepted JSON payloads
|
||||
#[structopt(long, env = "MEILI_HTTP_PAYLOAD_SIZE_LIMIT", default_value = "10485760")] // 10MB
|
||||
pub http_payload_size_limit: usize,
|
||||
#[structopt(long, env = "MEILI_HTTP_PAYLOAD_SIZE_LIMIT", default_value = "10 MiB")]
|
||||
pub http_payload_size_limit: Byte,
|
||||
|
||||
/// Read server certificates from CERTFILE.
|
||||
/// 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::{web, HttpResponse};
|
||||
use indexmap::IndexMap;
|
||||
use meilisearch_core::{update, MainReader};
|
||||
use serde_json::Value;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::Data;
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
||||
use crate::routes::IndexParam;
|
||||
|
||||
type Document = IndexMap<String, Value>;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DocumentParam {
|
||||
index_uid: String,
|
||||
document_id: String,
|
||||
_index_uid: String,
|
||||
_document_id: String,
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
@ -35,8 +32,8 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
wrap = "Authentication::Public"
|
||||
)]
|
||||
async fn get_document(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<DocumentParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<DocumentParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -46,8 +43,8 @@ async fn get_document(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_document(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<DocumentParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<DocumentParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -55,62 +52,51 @@ async fn delete_document(
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
struct BrowseQuery {
|
||||
offset: Option<usize>,
|
||||
limit: Option<usize>,
|
||||
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!()
|
||||
_offset: Option<usize>,
|
||||
_limit: Option<usize>,
|
||||
_attributes_to_retrieve: Option<String>,
|
||||
}
|
||||
|
||||
#[get("/indexes/{index_uid}/documents", wrap = "Authentication::Public")]
|
||||
async fn get_all_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<BrowseQuery>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_params: web::Query<BrowseQuery>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn find_primary_key(document: &IndexMap<String, Value>) -> Option<String> {
|
||||
for key in document.keys() {
|
||||
if key.to_lowercase().contains("id") {
|
||||
return Some(key.to_string());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
//fn find_primary_key(document: &IndexMap<String, Value>) -> Option<String> {
|
||||
//for key in document.keys() {
|
||||
//if key.to_lowercase().contains("id") {
|
||||
//return Some(key.to_string());
|
||||
//}
|
||||
//}
|
||||
//None
|
||||
//}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
struct UpdateDocumentsQuery {
|
||||
primary_key: Option<String>,
|
||||
_primary_key: Option<String>,
|
||||
}
|
||||
|
||||
async fn update_multiple_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<UpdateDocumentsQuery>,
|
||||
body: web::Json<Vec<Document>>,
|
||||
is_partial: bool,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_params: web::Query<UpdateDocumentsQuery>,
|
||||
_body: web::Json<Vec<Document>>,
|
||||
_is_partial: bool,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[post("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||
async fn add_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<UpdateDocumentsQuery>,
|
||||
body: web::Json<Vec<Document>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_params: web::Query<UpdateDocumentsQuery>,
|
||||
_body: web::Json<Vec<Document>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -130,17 +116,17 @@ async fn update_documents(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Vec<Value>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_body: web::Json<Vec<Value>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[delete("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||
async fn clear_all_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
@ -1,14 +1,10 @@
|
||||
use actix_web::{delete, get, post, put};
|
||||
use actix_web::{web, HttpResponse};
|
||||
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 crate::Data;
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
|
||||
@ -22,10 +18,6 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
.service(get_all_updates_status);
|
||||
}
|
||||
|
||||
fn generate_uid() -> String {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IndexResponse {
|
||||
@ -36,22 +28,15 @@ pub struct IndexResponse {
|
||||
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")]
|
||||
async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||
let reader = data.db.main_read_txn()?;
|
||||
let indexes = list_indexes_sync(&data, &reader)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(indexes))
|
||||
async fn list_indexes(_data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[get("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||
async fn get_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -64,20 +49,10 @@ struct IndexCreateRequest {
|
||||
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")]
|
||||
async fn create_index(
|
||||
data: web::Data<Data>,
|
||||
body: web::Json<IndexCreateRequest>,
|
||||
_data: web::Data<Data>,
|
||||
_body: web::Json<IndexCreateRequest>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -101,25 +76,25 @@ struct UpdateIndexResponse {
|
||||
|
||||
#[put("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||
async fn update_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<IndexCreateRequest>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_body: web::Json<IndexCreateRequest>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[delete("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||
async fn delete_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UpdateParam {
|
||||
index_uid: String,
|
||||
update_id: u64,
|
||||
_index_uid: String,
|
||||
_update_id: u64,
|
||||
}
|
||||
|
||||
#[get(
|
||||
@ -127,23 +102,16 @@ struct UpdateParam {
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get_update_status(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<UpdateParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<UpdateParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
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")]
|
||||
async fn get_all_updates_status(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
@ -17,6 +17,6 @@ struct KeysResponse {
|
||||
}
|
||||
|
||||
#[get("/keys", wrap = "Authentication::Admin")]
|
||||
async fn list(data: web::Data<Data>) -> HttpResponse {
|
||||
async fn list(_data: web::Data<Data>) -> HttpResponse {
|
||||
todo!()
|
||||
}
|
||||
|
@ -10,11 +10,11 @@ pub mod setting;
|
||||
pub mod stats;
|
||||
pub mod stop_words;
|
||||
pub mod synonym;
|
||||
pub mod dump;
|
||||
//pub mod dump;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct IndexParam {
|
||||
index_uid: String,
|
||||
_index_uid: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -1,19 +1,12 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use actix_web::{get, post, web, HttpResponse};
|
||||
use log::warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::error::{Error, FacetCountError, ResponseError};
|
||||
use crate::helpers::meilisearch::{IndexSearchExt, SearchResult};
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
|
||||
use meilisearch_core::facets::FacetFilter;
|
||||
use meilisearch_schema::{FieldId, Schema};
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
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")]
|
||||
async fn search_with_url_query(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<SearchQuery>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_params: web::Query<SearchQuery>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -46,53 +39,24 @@ async fn search_with_url_query(
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct SearchQueryPost {
|
||||
q: Option<String>,
|
||||
offset: Option<usize>,
|
||||
limit: Option<usize>,
|
||||
attributes_to_retrieve: Option<Vec<String>>,
|
||||
attributes_to_crop: Option<Vec<String>>,
|
||||
crop_length: Option<usize>,
|
||||
attributes_to_highlight: Option<Vec<String>>,
|
||||
filters: Option<String>,
|
||||
matches: Option<bool>,
|
||||
facet_filters: Option<Value>,
|
||||
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)),
|
||||
}
|
||||
}
|
||||
_q: Option<String>,
|
||||
_offset: Option<usize>,
|
||||
_limit: Option<usize>,
|
||||
_attributes_to_retrieve: Option<Vec<String>>,
|
||||
_attributes_to_crop: Option<Vec<String>>,
|
||||
_crop_length: Option<usize>,
|
||||
_attributes_to_highlight: Option<Vec<String>>,
|
||||
_filters: Option<String>,
|
||||
_matches: Option<bool>,
|
||||
_facet_filters: Option<Value>,
|
||||
_facets_distribution: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[post("/indexes/{index_uid}/search", wrap = "Authentication::Public")]
|
||||
async fn search_with_post(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Json<SearchQueryPost>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_params: web::Json<SearchQueryPost>,
|
||||
) -> 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!()
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use actix_web::{delete, get, post};
|
||||
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::error::{Error, ResponseError};
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
||||
use crate::updates::Settings;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(update_all)
|
||||
@ -32,27 +29,28 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
.service(update_attributes_for_faceting);
|
||||
}
|
||||
|
||||
|
||||
#[post("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||
async fn update_all(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Settings>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
_body: web::Json<Settings>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[get("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||
async fn get_all(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[delete("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||
async fn delete_all(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -62,8 +60,8 @@ async fn delete_all(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get_rules(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -73,9 +71,9 @@ async fn get_rules(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update_rules(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<Vec<String>>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
_body: web::Json<Option<Vec<String>>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -85,8 +83,8 @@ async fn update_rules(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_rules(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -96,8 +94,8 @@ async fn delete_rules(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get_distinct(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -107,9 +105,9 @@ async fn get_distinct(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update_distinct(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<String>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
_body: web::Json<Option<String>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -119,8 +117,8 @@ async fn update_distinct(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_distinct(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -130,8 +128,8 @@ async fn delete_distinct(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get_searchable(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -141,9 +139,9 @@ async fn get_searchable(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update_searchable(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<Vec<String>>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
_body: web::Json<Option<Vec<String>>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -153,8 +151,8 @@ async fn update_searchable(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_searchable(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -164,8 +162,8 @@ async fn delete_searchable(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get_displayed(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -175,9 +173,9 @@ async fn get_displayed(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update_displayed(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<BTreeSet<String>>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
_body: web::Json<Option<BTreeSet<String>>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -187,8 +185,8 @@ async fn update_displayed(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_displayed(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -198,8 +196,8 @@ async fn delete_displayed(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get_attributes_for_faceting(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -209,9 +207,9 @@ async fn get_attributes_for_faceting(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update_attributes_for_faceting(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Option<Vec<String>>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
_body: web::Json<Option<Vec<String>>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -221,8 +219,8 @@ async fn update_attributes_for_faceting(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_attributes_for_faceting(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
@ -4,11 +4,9 @@ use actix_web::web;
|
||||
use actix_web::HttpResponse;
|
||||
use actix_web::get;
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::error;
|
||||
use serde::Serialize;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
@ -29,8 +27,8 @@ struct IndexStatsResponse {
|
||||
|
||||
#[get("/indexes/{index_uid}/stats", wrap = "Authentication::Private")]
|
||||
async fn index_stats(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -44,7 +42,7 @@ struct StatsResult {
|
||||
}
|
||||
|
||||
#[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!()
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
use actix_web::{web, HttpResponse};
|
||||
use actix_web::{delete, get, post};
|
||||
use meilisearch_core::settings::{SettingsUpdate, UpdateState};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::{IndexParam, IndexUpdateResponse};
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
@ -17,8 +16,8 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -28,9 +27,9 @@ async fn get(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<BTreeSet<String>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_body: web::Json<BTreeSet<String>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -40,8 +39,8 @@ async fn update(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
@ -2,12 +2,10 @@ use std::collections::BTreeMap;
|
||||
|
||||
use actix_web::{web, HttpResponse};
|
||||
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::routes::{IndexParam, IndexUpdateResponse};
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
@ -19,8 +17,8 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -30,9 +28,9 @@ async fn get(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<BTreeMap<String, Vec<String>>>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_body: web::Json<BTreeMap<String, Vec<String>>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
@ -42,8 +40,8 @@ async fn update(
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
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