mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-04 12:27:13 +02:00
restructure project
This commit is contained in:
parent
8061a04661
commit
5ecf514d28
75 changed files with 4377 additions and 323 deletions
262
meilisearch-http/src/routes/document.rs
Normal file
262
meilisearch-http/src/routes/document.rs
Normal file
|
@ -0,0 +1,262 @@
|
|||
use actix_web::web::Payload;
|
||||
use actix_web::{delete, get, post, put};
|
||||
use actix_web::{web, HttpResponse};
|
||||
use indexmap::IndexMap;
|
||||
use log::error;
|
||||
use milli::update::{IndexDocumentsMethod, UpdateFormat};
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::Data;
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
|
||||
const DEFAULT_RETRIEVE_DOCUMENTS_OFFSET: usize = 0;
|
||||
const DEFAULT_RETRIEVE_DOCUMENTS_LIMIT: usize = 20;
|
||||
|
||||
macro_rules! guard_content_type {
|
||||
($fn_name:ident, $guard_value:literal) => {
|
||||
fn $fn_name(head: &actix_web::dev::RequestHead) -> bool {
|
||||
if let Some(content_type) = head.headers.get("Content-Type") {
|
||||
content_type.to_str().map(|v| v.contains($guard_value)).unwrap_or(false)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
guard_content_type!(guard_json, "application/json");
|
||||
|
||||
type Document = IndexMap<String, Value>;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DocumentParam {
|
||||
index_uid: String,
|
||||
document_id: String,
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(get_document)
|
||||
.service(delete_document)
|
||||
.service(get_all_documents)
|
||||
.service(add_documents_json)
|
||||
.service(update_documents)
|
||||
.service(delete_documents)
|
||||
.service(clear_all_documents);
|
||||
}
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/documents/{document_id}",
|
||||
wrap = "Authentication::Public"
|
||||
)]
|
||||
async fn get_document(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<DocumentParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = path.index_uid.clone();
|
||||
let id = path.document_id.clone();
|
||||
match data.retrieve_document(index, id, None as Option<Vec<String>>).await {
|
||||
Ok(document) => {
|
||||
let json = serde_json::to_string(&document).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[delete(
|
||||
"/indexes/{index_uid}/documents/{document_id}",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_document(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<DocumentParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.delete_documents(path.index_uid.clone(), vec![path.document_id.clone()]).await {
|
||||
Ok(result) => {
|
||||
let json = serde_json::to_string(&result).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
struct BrowseQuery {
|
||||
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>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let attributes_to_retrieve = params
|
||||
.attributes_to_retrieve
|
||||
.as_ref()
|
||||
.map(|attrs| attrs
|
||||
.split(",")
|
||||
.map(String::from)
|
||||
.collect::<Vec<_>>());
|
||||
|
||||
match data.retrieve_documents(
|
||||
path.index_uid.clone(),
|
||||
params.offset.unwrap_or(DEFAULT_RETRIEVE_DOCUMENTS_OFFSET),
|
||||
params.limit.unwrap_or(DEFAULT_RETRIEVE_DOCUMENTS_LIMIT),
|
||||
attributes_to_retrieve).await {
|
||||
Ok(docs) => {
|
||||
let json = serde_json::to_string(&docs).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
struct UpdateDocumentsQuery {
|
||||
primary_key: Option<String>,
|
||||
}
|
||||
|
||||
/// Route used when the payload type is "application/json"
|
||||
#[post(
|
||||
"/indexes/{index_uid}/documents",
|
||||
wrap = "Authentication::Private",
|
||||
guard = "guard_json"
|
||||
)]
|
||||
async fn add_documents_json(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<UpdateDocumentsQuery>,
|
||||
body: Payload,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let addition_result = data
|
||||
.add_documents(
|
||||
path.into_inner().index_uid,
|
||||
IndexDocumentsMethod::ReplaceDocuments,
|
||||
UpdateFormat::Json,
|
||||
body,
|
||||
params.primary_key.clone(),
|
||||
).await;
|
||||
|
||||
match addition_result {
|
||||
Ok(update) => {
|
||||
let value = serde_json::to_string(&update).unwrap();
|
||||
let response = HttpResponse::Ok().body(value);
|
||||
Ok(response)
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Default route for adding documents, this should return an error and redirect to the documentation
|
||||
#[post("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||
async fn add_documents_default(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_params: web::Query<UpdateDocumentsQuery>,
|
||||
_body: web::Json<Vec<Document>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
error!("Unknown document type");
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Default route for adding documents, this should return an error and redirect to the documentation
|
||||
#[put("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||
async fn update_documents_default(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_params: web::Query<UpdateDocumentsQuery>,
|
||||
_body: web::Json<Vec<Document>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
error!("Unknown document type");
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[put(
|
||||
"/indexes/{index_uid}/documents",
|
||||
wrap = "Authentication::Private",
|
||||
guard = "guard_json",
|
||||
)]
|
||||
async fn update_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
params: web::Query<UpdateDocumentsQuery>,
|
||||
body: web::Payload,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let addition_result = data
|
||||
.add_documents(
|
||||
path.into_inner().index_uid,
|
||||
IndexDocumentsMethod::UpdateDocuments,
|
||||
UpdateFormat::Json,
|
||||
body,
|
||||
params.primary_key.clone(),
|
||||
).await;
|
||||
|
||||
match addition_result {
|
||||
Ok(update) => {
|
||||
let value = serde_json::to_string(&update).unwrap();
|
||||
let response = HttpResponse::Ok().body(value);
|
||||
Ok(response)
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[post(
|
||||
"/indexes/{index_uid}/documents/delete-batch",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<Vec<Value>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let ids = body
|
||||
.iter()
|
||||
.map(|v| v.as_str().map(String::from).unwrap_or_else(|| v.to_string()))
|
||||
.collect();
|
||||
|
||||
match data.delete_documents(path.index_uid.clone(), ids).await {
|
||||
Ok(result) => {
|
||||
let json = serde_json::to_string(&result).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[delete("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
|
||||
async fn clear_all_documents(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.clear_documents(path.index_uid.clone()).await {
|
||||
Ok(update) => {
|
||||
let json = serde_json::to_string(&update).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
42
meilisearch-http/src/routes/dump.rs
Normal file
42
meilisearch-http/src/routes/dump.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use actix_web::{get, post};
|
||||
use actix_web::{HttpResponse, web};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::dump::{DumpInfo, DumpStatus, compressed_dumps_dir, init_dump_process};
|
||||
use crate::Data;
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(trigger_dump)
|
||||
.service(get_dump_status);
|
||||
}
|
||||
|
||||
#[post("/dumps", wrap = "Authentication::Private")]
|
||||
async fn trigger_dump(
|
||||
data: web::Data<Data>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct DumpStatusResponse {
|
||||
status: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DumpParam {
|
||||
dump_uid: String,
|
||||
}
|
||||
|
||||
#[get("/dumps/{dump_uid}/status", wrap = "Authentication::Private")]
|
||||
async fn get_dump_status(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<DumpParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
13
meilisearch-http/src/routes/health.rs
Normal file
13
meilisearch-http/src/routes/health.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use actix_web::get;
|
||||
use actix_web::{web, HttpResponse};
|
||||
|
||||
use crate::error::ResponseError;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(get_health);
|
||||
}
|
||||
|
||||
#[get("/health")]
|
||||
async fn get_health() -> Result<HttpResponse, ResponseError> {
|
||||
Ok(HttpResponse::NoContent().finish())
|
||||
}
|
167
meilisearch-http/src/routes/index.rs
Normal file
167
meilisearch-http/src/routes/index.rs
Normal file
|
@ -0,0 +1,167 @@
|
|||
use actix_web::{delete, get, post, put};
|
||||
use actix_web::{web, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Data;
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(list_indexes)
|
||||
.service(get_index)
|
||||
.service(create_index)
|
||||
.service(update_index)
|
||||
.service(delete_index)
|
||||
.service(get_update_status)
|
||||
.service(get_all_updates_status);
|
||||
}
|
||||
|
||||
|
||||
#[get("/indexes", wrap = "Authentication::Private")]
|
||||
async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||
match data.list_indexes().await {
|
||||
Ok(indexes) => {
|
||||
let json = serde_json::to_string(&indexes).unwrap();
|
||||
Ok(HttpResponse::Ok().body(&json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||
async fn get_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.index(&path.index_uid).await? {
|
||||
Some(meta) => {
|
||||
let json = serde_json::to_string(&meta).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
None => {
|
||||
let e = format!("Index {:?} doesn't exist.", path.index_uid);
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
struct IndexCreateRequest {
|
||||
uid: String,
|
||||
primary_key: Option<String>,
|
||||
}
|
||||
|
||||
#[post("/indexes", wrap = "Authentication::Private")]
|
||||
async fn create_index(
|
||||
data: web::Data<Data>,
|
||||
body: web::Json<IndexCreateRequest>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.create_index(&body.uid, body.primary_key.clone()).await {
|
||||
Ok(meta) => {
|
||||
let json = serde_json::to_string(&meta).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
struct UpdateIndexRequest {
|
||||
name: Option<String>,
|
||||
primary_key: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct UpdateIndexResponse {
|
||||
name: String,
|
||||
uid: String,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
primary_key: Option<String>,
|
||||
}
|
||||
|
||||
#[put("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||
async fn update_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
body: web::Json<UpdateIndexRequest>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.update_index(&path.index_uid, body.primary_key.as_ref(), body.name.as_ref()) {
|
||||
Ok(meta) => {
|
||||
let json = serde_json::to_string(&meta).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[delete("/indexes/{index_uid}", wrap = "Authentication::Private")]
|
||||
async fn delete_index(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.delete_index(path.index_uid.clone()).await {
|
||||
Ok(_) => Ok(HttpResponse::Ok().finish()),
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UpdateParam {
|
||||
index_uid: String,
|
||||
update_id: u64,
|
||||
}
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/updates/{update_id}",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get_update_status(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<UpdateParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let result = data.get_update_status(&path.index_uid, path.update_id).await;
|
||||
match result {
|
||||
Ok(Some(meta)) => {
|
||||
let json = serde_json::to_string(&meta).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Ok(None) => {
|
||||
let e = format!("udpate {} for index {:?} doesn't exists.", path.update_id, path.index_uid);
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/indexes/{index_uid}/updates", wrap = "Authentication::Private")]
|
||||
async fn get_all_updates_status(
|
||||
data: web::Data<Data>,
|
||||
path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let result = data.get_updates_status(&path.index_uid).await;
|
||||
match result {
|
||||
Ok(metas) => {
|
||||
let json = serde_json::to_string(&metas).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
26
meilisearch-http/src/routes/key.rs
Normal file
26
meilisearch-http/src/routes/key.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use actix_web::web;
|
||||
use actix_web::HttpResponse;
|
||||
use actix_web::get;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::helpers::Authentication;
|
||||
use crate::Data;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(list);
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct KeysResponse {
|
||||
private: Option<String>,
|
||||
public: Option<String>,
|
||||
}
|
||||
|
||||
#[get("/keys", wrap = "Authentication::Admin")]
|
||||
async fn list(data: web::Data<Data>) -> HttpResponse {
|
||||
let api_keys = data.api_keys.clone();
|
||||
HttpResponse::Ok().json(&KeysResponse {
|
||||
private: api_keys.private,
|
||||
public: api_keys.public,
|
||||
})
|
||||
}
|
44
meilisearch-http/src/routes/mod.rs
Normal file
44
meilisearch-http/src/routes/mod.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use actix_web::{get, HttpResponse};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod document;
|
||||
pub mod health;
|
||||
pub mod index;
|
||||
pub mod key;
|
||||
pub mod search;
|
||||
pub mod settings;
|
||||
pub mod stats;
|
||||
pub mod stop_words;
|
||||
pub mod synonym;
|
||||
//pub mod dump;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct IndexParam {
|
||||
index_uid: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IndexUpdateResponse {
|
||||
pub update_id: u64,
|
||||
}
|
||||
|
||||
impl IndexUpdateResponse {
|
||||
pub fn with_id(update_id: u64) -> Self {
|
||||
Self { update_id }
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
pub async fn load_html() -> HttpResponse {
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(include_str!("../../public/interface.html").to_string())
|
||||
}
|
||||
|
||||
#[get("/bulma.min.css")]
|
||||
pub async fn load_css() -> HttpResponse {
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/css; charset=utf-8")
|
||||
.body(include_str!("../../public/bulma.min.css").to_string())
|
||||
}
|
114
meilisearch-http/src/routes/search.rs
Normal file
114
meilisearch-http/src/routes/search.rs
Normal file
|
@ -0,0 +1,114 @@
|
|||
use std::collections::HashSet;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
use actix_web::{get, post, web, HttpResponse};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
use crate::index::{SearchQuery, DEFAULT_SEARCH_LIMIT};
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(search_with_post).service(search_with_url_query);
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct SearchQueryGet {
|
||||
q: Option<String>,
|
||||
offset: Option<usize>,
|
||||
limit: Option<usize>,
|
||||
attributes_to_retrieve: Option<String>,
|
||||
attributes_to_crop: Option<String>,
|
||||
crop_length: Option<usize>,
|
||||
attributes_to_highlight: Option<String>,
|
||||
filters: Option<String>,
|
||||
matches: Option<bool>,
|
||||
facet_filters: Option<String>,
|
||||
facet_distributions: Option<String>,
|
||||
}
|
||||
|
||||
impl TryFrom<SearchQueryGet> for SearchQuery {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(other: SearchQueryGet) -> anyhow::Result<Self> {
|
||||
let attributes_to_retrieve = other
|
||||
.attributes_to_retrieve
|
||||
.map(|attrs| attrs.split(",").map(String::from).collect::<Vec<_>>());
|
||||
|
||||
let attributes_to_crop = other
|
||||
.attributes_to_crop
|
||||
.map(|attrs| attrs.split(",").map(String::from).collect::<Vec<_>>());
|
||||
|
||||
let attributes_to_highlight = other
|
||||
.attributes_to_highlight
|
||||
.map(|attrs| attrs.split(",").map(String::from).collect::<HashSet<_>>());
|
||||
|
||||
let facet_distributions = other
|
||||
.facet_distributions
|
||||
.map(|attrs| attrs.split(",").map(String::from).collect::<Vec<_>>());
|
||||
|
||||
let facet_filters = match other.facet_filters {
|
||||
Some(ref f) => Some(serde_json::from_str(f)?),
|
||||
None => None,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
q: other.q,
|
||||
offset: other.offset,
|
||||
limit: other.limit.unwrap_or(DEFAULT_SEARCH_LIMIT),
|
||||
attributes_to_retrieve,
|
||||
attributes_to_crop,
|
||||
crop_length: other.crop_length,
|
||||
attributes_to_highlight,
|
||||
filters: other.filters,
|
||||
matches: other.matches,
|
||||
facet_filters,
|
||||
facet_distributions,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[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<SearchQueryGet>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let query: SearchQuery = match params.into_inner().try_into() {
|
||||
Ok(q) => q,
|
||||
Err(e) => {
|
||||
return Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
};
|
||||
let search_result = data.search(&path.index_uid, query).await;
|
||||
match search_result {
|
||||
Ok(docs) => {
|
||||
let docs = serde_json::to_string(&docs).unwrap();
|
||||
Ok(HttpResponse::Ok().body(docs))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_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<SearchQuery>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let search_result = data.search(&path.index_uid, params.into_inner()).await;
|
||||
match search_result {
|
||||
Ok(docs) => {
|
||||
let docs = serde_json::to_string(&docs).unwrap();
|
||||
Ok(HttpResponse::Ok().body(docs))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
use actix_web::{web, HttpResponse, get};
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
use crate::make_update_delete_routes;
|
||||
use crate::Data;
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/attributes-for-faceting",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.load()
|
||||
.open_index(&index_uid.as_ref())
|
||||
.ok_or(Error::index_not_found(&index_uid.as_ref()))?;
|
||||
|
||||
let attributes_for_faceting = data.db.load().main_read::<_, _, ResponseError>(|reader| {
|
||||
let schema = index.main.schema(reader)?;
|
||||
let attrs = index.main.attributes_for_faceting(reader)?;
|
||||
let attr_names = match (&schema, &attrs) {
|
||||
(Some(schema), Some(attrs)) => attrs
|
||||
.iter()
|
||||
.filter_map(|&id| schema.name(id))
|
||||
.map(str::to_string)
|
||||
.collect(),
|
||||
_ => vec![],
|
||||
};
|
||||
Ok(attr_names)
|
||||
})?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(attributes_for_faceting))
|
||||
}
|
||||
|
||||
make_update_delete_routes!(
|
||||
"/indexes/{index_uid}/settings/attributes-for-faceting",
|
||||
Vec<String>,
|
||||
attributes_for_faceting
|
||||
);
|
25
meilisearch-http/src/routes/settings/displayed_attributes.rs
Normal file
25
meilisearch-http/src/routes/settings/displayed_attributes.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use actix_web::{web, HttpResponse, get};
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
use crate::make_update_delete_routes;
|
||||
use crate::Data;
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/displayed-attributes",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
make_update_delete_routes!(
|
||||
"/indexes/{index_uid}/settings/displayed-attributes",
|
||||
HashSet<String>,
|
||||
displayed_attributes
|
||||
);
|
36
meilisearch-http/src/routes/settings/distinct_attributes.rs
Normal file
36
meilisearch-http/src/routes/settings/distinct_attributes.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use crate::make_update_delete_routes;
|
||||
use actix_web::{web, HttpResponse, get};
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
use crate::Data;
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/distinct-attribute",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.load()
|
||||
.open_index(&index_uid.as_ref())
|
||||
.ok_or(Error::index_not_found(&index_uid.as_ref()))?;
|
||||
let reader = data.db.load().main_read_txn()?;
|
||||
let distinct_attribute_id = index.main.distinct_attribute(&reader)?;
|
||||
let schema = index.main.schema(&reader)?;
|
||||
let distinct_attribute = match (schema, distinct_attribute_id) {
|
||||
(Some(schema), Some(id)) => schema.name(id).map(str::to_string),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().json(distinct_attribute))
|
||||
}
|
||||
|
||||
make_update_delete_routes!(
|
||||
"/indexes/{index_uid}/settings/distinct-attribute",
|
||||
String,
|
||||
distinct_attribute
|
||||
);
|
183
meilisearch-http/src/routes/settings/mod.rs
Normal file
183
meilisearch-http/src/routes/settings/mod.rs
Normal file
|
@ -0,0 +1,183 @@
|
|||
use actix_web::{web, HttpResponse, delete, get, post};
|
||||
|
||||
use crate::Data;
|
||||
use crate::error::ResponseError;
|
||||
use crate::index::Settings;
|
||||
use crate::helpers::Authentication;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! make_setting_route {
|
||||
($route:literal, $type:ty, $attr:ident) => {
|
||||
mod $attr {
|
||||
use actix_web::{web, HttpResponse};
|
||||
|
||||
use crate::data;
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::index::Settings;
|
||||
|
||||
#[actix_web::delete($route, wrap = "Authentication::Private")]
|
||||
pub async fn delete(
|
||||
data: web::Data<data::Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
use crate::index::Settings;
|
||||
let settings = Settings {
|
||||
$attr: Some(None),
|
||||
..Default::default()
|
||||
};
|
||||
match data.update_settings(index_uid.into_inner(), settings).await {
|
||||
Ok(update_status) => {
|
||||
let json = serde_json::to_string(&update_status).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::post($route, wrap = "Authentication::Private")]
|
||||
pub async fn update(
|
||||
data: actix_web::web::Data<data::Data>,
|
||||
index_uid: actix_web::web::Path<String>,
|
||||
body: actix_web::web::Json<Option<$type>>,
|
||||
) -> std::result::Result<HttpResponse, ResponseError> {
|
||||
let settings = Settings {
|
||||
$attr: Some(body.into_inner()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
match data.update_settings(index_uid.into_inner(), settings).await {
|
||||
Ok(update_status) => {
|
||||
let json = serde_json::to_string(&update_status).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::get($route, wrap = "Authentication::Private")]
|
||||
pub async fn get(
|
||||
data: actix_web::web::Data<data::Data>,
|
||||
index_uid: actix_web::web::Path<String>,
|
||||
) -> std::result::Result<HttpResponse, ResponseError> {
|
||||
match data.settings(index_uid.as_ref()).await {
|
||||
Ok(settings) => {
|
||||
let setting = settings.$attr;
|
||||
let json = serde_json::to_string(&setting).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
make_setting_route!(
|
||||
"/indexes/{index_uid}/settings/attributes-for-faceting",
|
||||
std::collections::HashMap<String, String>,
|
||||
faceted_attributes
|
||||
);
|
||||
|
||||
make_setting_route!(
|
||||
"/indexes/{index_uid}/settings/displayed-attributes",
|
||||
Vec<String>,
|
||||
displayed_attributes
|
||||
);
|
||||
|
||||
make_setting_route!(
|
||||
"/indexes/{index_uid}/settings/searchable-attributes",
|
||||
Vec<String>,
|
||||
searchable_attributes
|
||||
);
|
||||
|
||||
//make_setting_route!(
|
||||
//"/indexes/{index_uid}/settings/distinct-attribute",
|
||||
//String,
|
||||
//distinct_attribute
|
||||
//);
|
||||
|
||||
//make_setting_route!(
|
||||
//"/indexes/{index_uid}/settings/ranking-rules",
|
||||
//Vec<String>,
|
||||
//ranking_rules
|
||||
//);
|
||||
|
||||
macro_rules! create_services {
|
||||
($($mod:ident),*) => {
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg
|
||||
.service(update_all)
|
||||
.service(get_all)
|
||||
.service(delete_all)
|
||||
$(
|
||||
.service($mod::get)
|
||||
.service($mod::update)
|
||||
.service($mod::delete)
|
||||
)*;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
create_services!(
|
||||
faceted_attributes,
|
||||
displayed_attributes,
|
||||
searchable_attributes
|
||||
);
|
||||
|
||||
#[post("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||
async fn update_all(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
body: web::Json<Settings>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.update_settings(index_uid.into_inner(), body.into_inner()).await {
|
||||
Ok(update_result) => {
|
||||
let json = serde_json::to_string(&update_result).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||
async fn get_all(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
match data.settings(index_uid.as_ref()).await {
|
||||
Ok(settings) => {
|
||||
let json = serde_json::to_string(&settings).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[delete("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
|
||||
async fn delete_all(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let settings = Settings::cleared();
|
||||
match data.update_settings(index_uid.into_inner(), settings).await {
|
||||
Ok(update_result) => {
|
||||
let json = serde_json::to_string(&update_result).unwrap();
|
||||
Ok(HttpResponse::Ok().body(json))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(HttpResponse::BadRequest().body(serde_json::json!({ "error": e.to_string() })))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
23
meilisearch-http/src/routes/settings/ranking_rules.rs
Normal file
23
meilisearch-http/src/routes/settings/ranking_rules.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use crate::make_update_delete_routes;
|
||||
use actix_web::{web, HttpResponse, get};
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
use crate::Data;
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/ranking-rules",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
make_update_delete_routes!(
|
||||
"/indexes/{index_uid}/settings/ranking-rules",
|
||||
Vec<String>,
|
||||
ranking_rules
|
||||
);
|
|
@ -0,0 +1,34 @@
|
|||
use actix_web::{web, HttpResponse, get};
|
||||
|
||||
use crate::data::get_indexed_attributes;
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
use crate::make_update_delete_routes;
|
||||
use crate::Data;
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/searchable-attributes",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.load()
|
||||
.open_index(&index_uid.as_ref())
|
||||
|
||||
.ok_or(Error::index_not_found(&index_uid.as_ref()))?;
|
||||
let reader = data.db.load().main_read_txn()?;
|
||||
let schema = index.main.schema(&reader)?;
|
||||
let searchable_attributes: Option<Vec<String>> = schema.as_ref().map(get_indexed_attributes);
|
||||
|
||||
Ok(HttpResponse::Ok().json(searchable_attributes))
|
||||
}
|
||||
|
||||
make_update_delete_routes!(
|
||||
"/indexes/{index_uid}/settings/searchable-attributes",
|
||||
Vec<String>,
|
||||
searchable_attributes
|
||||
);
|
33
meilisearch-http/src/routes/settings/stop_words.rs
Normal file
33
meilisearch-http/src/routes/settings/stop_words.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::make_update_delete_routes;
|
||||
use actix_web::{web, HttpResponse, get};
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
use crate::Data;
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/stop-words",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.load()
|
||||
.open_index(&index_uid.as_ref())
|
||||
.ok_or(Error::index_not_found(&index_uid.as_ref()))?;
|
||||
let reader = data.db.load().main_read_txn()?;
|
||||
let stop_words = index.main.stop_words(&reader)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(stop_words))
|
||||
}
|
||||
|
||||
make_update_delete_routes!(
|
||||
"/indexes/{index_uid}/settings/stop-words",
|
||||
BTreeSet<String>,
|
||||
stop_words
|
||||
);
|
43
meilisearch-http/src/routes/settings/synonyms.rs
Normal file
43
meilisearch-http/src/routes/settings/synonyms.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use actix_web::{web, HttpResponse, get};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use crate::error::{Error, ResponseError};
|
||||
use crate::helpers::Authentication;
|
||||
use crate::make_update_delete_routes;
|
||||
use crate::Data;
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/synonyms",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
data: web::Data<Data>,
|
||||
index_uid: web::Path<String>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
let index = data
|
||||
.db
|
||||
.load()
|
||||
.open_index(&index_uid.as_ref())
|
||||
.ok_or(Error::index_not_found(&index_uid.as_ref()))?;
|
||||
|
||||
let reader = data.db.load().main_read_txn()?;
|
||||
|
||||
let synonyms_list = index.main.synonyms(&reader)?;
|
||||
|
||||
let mut synonyms = IndexMap::new();
|
||||
let index_synonyms = &index.synonyms;
|
||||
for synonym in synonyms_list {
|
||||
let list = index_synonyms.synonyms(&reader, synonym.as_bytes())?;
|
||||
synonyms.insert(synonym, list);
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().json(synonyms))
|
||||
}
|
||||
|
||||
make_update_delete_routes!(
|
||||
"/indexes/{index_uid}/settings/synonyms",
|
||||
BTreeMap<String, Vec<String>>,
|
||||
synonyms
|
||||
);
|
60
meilisearch-http/src/routes/stats.rs
Normal file
60
meilisearch-http/src/routes/stats.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
use std::collections::{HashMap, BTreeMap};
|
||||
|
||||
use actix_web::web;
|
||||
use actix_web::HttpResponse;
|
||||
use actix_web::get;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(index_stats)
|
||||
.service(get_stats)
|
||||
.service(get_version);
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct IndexStatsResponse {
|
||||
number_of_documents: u64,
|
||||
is_indexing: bool,
|
||||
fields_distribution: BTreeMap<String, usize>,
|
||||
}
|
||||
|
||||
#[get("/indexes/{index_uid}/stats", wrap = "Authentication::Private")]
|
||||
async fn index_stats(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct StatsResult {
|
||||
database_size: u64,
|
||||
last_update: Option<DateTime<Utc>>,
|
||||
indexes: HashMap<String, IndexStatsResponse>,
|
||||
}
|
||||
|
||||
#[get("/stats", wrap = "Authentication::Private")]
|
||||
async fn get_stats(_data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct VersionResponse {
|
||||
commit_sha: String,
|
||||
build_date: String,
|
||||
pkg_version: String,
|
||||
}
|
||||
|
||||
#[get("/version", wrap = "Authentication::Private")]
|
||||
async fn get_version() -> HttpResponse {
|
||||
todo!()
|
||||
}
|
46
meilisearch-http/src/routes/stop_words.rs
Normal file
46
meilisearch-http/src/routes/stop_words.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use actix_web::{web, HttpResponse};
|
||||
use actix_web::{delete, get, post};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(get).service(update).service(delete);
|
||||
}
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/stop-words",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[post(
|
||||
"/indexes/{index_uid}/settings/stop-words",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_body: web::Json<BTreeSet<String>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[delete(
|
||||
"/indexes/{index_uid}/settings/stop-words",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
47
meilisearch-http/src/routes/synonym.rs
Normal file
47
meilisearch-http/src/routes/synonym.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use actix_web::{web, HttpResponse};
|
||||
use actix_web::{delete, get, post};
|
||||
|
||||
use crate::error::ResponseError;
|
||||
use crate::helpers::Authentication;
|
||||
use crate::routes::IndexParam;
|
||||
use crate::Data;
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(get).service(update).service(delete);
|
||||
}
|
||||
|
||||
#[get(
|
||||
"/indexes/{index_uid}/settings/synonyms",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn get(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[post(
|
||||
"/indexes/{index_uid}/settings/synonyms",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn update(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
_body: web::Json<BTreeMap<String, Vec<String>>>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[delete(
|
||||
"/indexes/{index_uid}/settings/synonyms",
|
||||
wrap = "Authentication::Private"
|
||||
)]
|
||||
async fn delete(
|
||||
_data: web::Data<Data>,
|
||||
_path: web::Path<IndexParam>,
|
||||
) -> Result<HttpResponse, ResponseError> {
|
||||
todo!()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue