mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-04 20:37:15 +02:00
Implements the get and delete tasks route
This commit is contained in:
parent
f00a285a6d
commit
742d0ee531
25 changed files with 1787 additions and 85 deletions
|
@ -31,6 +31,7 @@ use tempfile::tempfile;
|
|||
use tokio::fs::File;
|
||||
use tokio::io::{AsyncSeekExt, AsyncWriteExt, BufWriter};
|
||||
use tracing::debug;
|
||||
use utoipa::{IntoParams, OpenApi, ToSchema};
|
||||
|
||||
use crate::analytics::{Aggregate, AggregateMethod, Analytics};
|
||||
use crate::error::MeilisearchHttpError;
|
||||
|
@ -71,6 +72,19 @@ pub struct DocumentParam {
|
|||
document_id: String,
|
||||
}
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
paths(get_documents, replace_documents, update_documents, clear_all_documents, delete_documents_batch),
|
||||
tags(
|
||||
(
|
||||
name = "Documents",
|
||||
description = "Documents are objects composed of fields that can store any type of data. Each field contains an attribute and its associated value. Documents are stored inside [indexes](https://www.meilisearch.com/docs/learn/getting_started/indexes).",
|
||||
external_docs(url = "https://www.meilisearch.com/docs/learn/getting_started/documents"),
|
||||
),
|
||||
),
|
||||
)]
|
||||
pub struct DocumentsApi;
|
||||
|
||||
pub fn configure(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(
|
||||
web::resource("")
|
||||
|
@ -286,17 +300,23 @@ pub struct BrowseQueryGet {
|
|||
filter: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserr)]
|
||||
#[derive(Debug, Deserr, IntoParams, ToSchema)]
|
||||
#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)]
|
||||
#[schema(rename_all = "camelCase")]
|
||||
pub struct BrowseQuery {
|
||||
#[schema(default, example = 150)]
|
||||
#[deserr(default, error = DeserrJsonError<InvalidDocumentOffset>)]
|
||||
offset: usize,
|
||||
#[schema(default = 20, example = 1)]
|
||||
#[deserr(default = PAGINATION_DEFAULT_LIMIT, error = DeserrJsonError<InvalidDocumentLimit>)]
|
||||
limit: usize,
|
||||
#[schema(example = json!(["title, description"]))]
|
||||
#[deserr(default, error = DeserrJsonError<InvalidDocumentFields>)]
|
||||
fields: Option<Vec<String>>,
|
||||
#[schema(default, example = true)]
|
||||
#[deserr(default, error = DeserrJsonError<InvalidDocumentRetrieveVectors>)]
|
||||
retrieve_vectors: bool,
|
||||
#[schema(default, example = "popularity > 1000")]
|
||||
#[deserr(default, error = DeserrJsonError<InvalidDocumentFilter>)]
|
||||
filter: Option<Value>,
|
||||
}
|
||||
|
@ -326,6 +346,62 @@ pub async fn documents_by_query_post(
|
|||
documents_by_query(&index_scheduler, index_uid, body)
|
||||
}
|
||||
|
||||
/// Get documents
|
||||
///
|
||||
/// Get documents by batches.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/{indexUid}/documents",
|
||||
tags = ["Indexes", "Documents"],
|
||||
security(("Bearer" = ["documents.get", "documents.*", "*"])),
|
||||
params(
|
||||
("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false),
|
||||
// Here we can use the post version of the browse query since it contains the exact same parameter
|
||||
BrowseQuery
|
||||
),
|
||||
responses(
|
||||
// body = PaginationView<Document>
|
||||
(status = 200, description = "The documents are returned", body = serde_json::Value, content_type = "application/json", example = json!(
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": 25684,
|
||||
"title": "American Ninja 5",
|
||||
"poster": "https://image.tmdb.org/t/p/w1280/iuAQVI4mvjI83wnirpD8GVNRVuY.jpg",
|
||||
"overview": "When a scientists daughter is kidnapped, American Ninja, attempts to find her, but this time he teams up with a youngster he has trained in the ways of the ninja.",
|
||||
"release_date": 725846400
|
||||
},
|
||||
{
|
||||
"id": 45881,
|
||||
"title": "The Bridge of San Luis Rey",
|
||||
"poster": "https://image.tmdb.org/t/p/w500/4X7quIcdkc24Cveg5XdpfRqxtYA.jpg",
|
||||
"overview": "The Bridge of San Luis Rey is American author Thornton Wilder's second novel, first published in 1927 to worldwide acclaim. It tells the story of several interrelated people who die in the collapse of an Inca rope-fiber suspension bridge in Peru, and the events that lead up to their being on the bridge.[ A friar who has witnessed the tragic accident then goes about inquiring into the lives of the victims, seeking some sort of cosmic answer to the question of why each had to die. The novel won the Pulitzer Prize in 1928.",
|
||||
"release_date": 1072915200
|
||||
}
|
||||
],
|
||||
"limit": 20,
|
||||
"offset": 0,
|
||||
"total": 2
|
||||
}
|
||||
)),
|
||||
(status = 404, description = "Index not found", body = ResponseError, content_type = "application/json", example = json!(
|
||||
{
|
||||
"message": "Index `movies` not found.",
|
||||
"code": "index_not_found",
|
||||
"type": "invalid_request",
|
||||
"link": "https://docs.meilisearch.com/errors#index_not_found"
|
||||
}
|
||||
)),
|
||||
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
|
||||
{
|
||||
"message": "The Authorization header is missing. It must use the bearer authorization method.",
|
||||
"code": "missing_authorization_header",
|
||||
"type": "auth",
|
||||
"link": "https://docs.meilisearch.com/errors#missing_authorization_header"
|
||||
}
|
||||
)),
|
||||
)
|
||||
)]
|
||||
pub async fn get_documents(
|
||||
index_scheduler: GuardedData<ActionPolicy<{ actions::DOCUMENTS_GET }>, Data<IndexScheduler>>,
|
||||
index_uid: web::Path<String>,
|
||||
|
@ -396,11 +472,17 @@ fn documents_by_query(
|
|||
Ok(HttpResponse::Ok().json(ret))
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Deserr)]
|
||||
#[derive(Deserialize, Debug, Deserr, IntoParams)]
|
||||
#[deserr(error = DeserrQueryParamError, rename_all = camelCase, deny_unknown_fields)]
|
||||
#[into_params(rename_all = "camelCase")]
|
||||
pub struct UpdateDocumentsQuery {
|
||||
/// The primary key of the documents. primaryKey is optional. If you want to set the primary key of your index through this route,
|
||||
/// it only has to be done the first time you add documents to the index. After which it will be ignored if given.
|
||||
#[param(example = "id")]
|
||||
#[deserr(default, error = DeserrQueryParamError<InvalidIndexPrimaryKey>)]
|
||||
pub primary_key: Option<String>,
|
||||
/// Customize the csv delimiter when importing CSV documents.
|
||||
#[param(value_type = char, default = ",", example = ";")]
|
||||
#[deserr(default, try_from(char) = from_char_csv_delimiter -> DeserrQueryParamError<InvalidDocumentCsvDelimiter>, error = DeserrQueryParamError<InvalidDocumentCsvDelimiter>)]
|
||||
pub csv_delimiter: Option<u8>,
|
||||
}
|
||||
|
@ -451,6 +533,51 @@ impl<Method: AggregateMethod> Aggregate for DocumentsAggregator<Method> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add or replace documents
|
||||
///
|
||||
/// Add a list of documents or replace them if they already exist.
|
||||
///
|
||||
/// If you send an already existing document (same id) the whole existing document will be overwritten by the new document. Fields previously in the document not present in the new document are removed.
|
||||
///
|
||||
/// For a partial update of the document see Add or update documents route.
|
||||
/// > info
|
||||
/// > If the provided index does not exist, it will be created.
|
||||
/// > info
|
||||
/// > Use the reserved `_geo` object to add geo coordinates to a document. `_geo` is an object made of `lat` and `lng` field.
|
||||
/// >
|
||||
/// > When the vectorStore feature is enabled you can use the reserved `_vectors` field in your documents.
|
||||
/// > It can accept an array of floats, multiple arrays of floats in an outer array or an object.
|
||||
/// > This object accepts keys corresponding to the different embedders defined your index settings.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/{indexUid}/documents",
|
||||
tags = ["Indexes", "Documents"],
|
||||
security(("Bearer" = ["documents.add", "documents.*", "*"])),
|
||||
params(
|
||||
("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false),
|
||||
// Here we can use the post version of the browse query since it contains the exact same parameter
|
||||
UpdateDocumentsQuery,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Task successfully enqueued", body = SummarizedTaskView, content_type = "application/json", example = json!(
|
||||
{
|
||||
"taskUid": 147,
|
||||
"indexUid": null,
|
||||
"status": "enqueued",
|
||||
"type": "documentAdditionOrUpdate",
|
||||
"enqueuedAt": "2024-08-08T17:05:55.791772Z"
|
||||
}
|
||||
)),
|
||||
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
|
||||
{
|
||||
"message": "The Authorization header is missing. It must use the bearer authorization method.",
|
||||
"code": "missing_authorization_header",
|
||||
"type": "auth",
|
||||
"link": "https://docs.meilisearch.com/errors#missing_authorization_header"
|
||||
}
|
||||
)),
|
||||
)
|
||||
)]
|
||||
pub async fn replace_documents(
|
||||
index_scheduler: GuardedData<ActionPolicy<{ actions::DOCUMENTS_ADD }>, Data<IndexScheduler>>,
|
||||
index_uid: web::Path<String>,
|
||||
|
@ -508,6 +635,49 @@ pub async fn replace_documents(
|
|||
Ok(HttpResponse::Accepted().json(task))
|
||||
}
|
||||
|
||||
/// Add or update documents
|
||||
///
|
||||
/// Add a list of documents or update them if they already exist.
|
||||
/// If you send an already existing document (same id) the old document will be only partially updated according to the fields of the new document. Thus, any fields not present in the new document are kept and remained unchanged.
|
||||
/// To completely overwrite a document, see Add or replace documents route.
|
||||
/// > info
|
||||
/// > If the provided index does not exist, it will be created.
|
||||
/// > info
|
||||
/// > Use the reserved `_geo` object to add geo coordinates to a document. `_geo` is an object made of `lat` and `lng` field.
|
||||
/// >
|
||||
/// > When the vectorStore feature is enabled you can use the reserved `_vectors` field in your documents.
|
||||
/// > It can accept an array of floats, multiple arrays of floats in an outer array or an object.
|
||||
/// > This object accepts keys corresponding to the different embedders defined your index settings.
|
||||
#[utoipa::path(
|
||||
put,
|
||||
path = "/{indexUid}/documents",
|
||||
tags = ["Indexes", "Documents"],
|
||||
security(("Bearer" = ["documents.add", "documents.*", "*"])),
|
||||
params(
|
||||
("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false),
|
||||
// Here we can use the post version of the browse query since it contains the exact same parameter
|
||||
UpdateDocumentsQuery,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Task successfully enqueued", body = SummarizedTaskView, content_type = "application/json", example = json!(
|
||||
{
|
||||
"taskUid": 147,
|
||||
"indexUid": null,
|
||||
"status": "enqueued",
|
||||
"type": "documentAdditionOrUpdate",
|
||||
"enqueuedAt": "2024-08-08T17:05:55.791772Z"
|
||||
}
|
||||
)),
|
||||
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
|
||||
{
|
||||
"message": "The Authorization header is missing. It must use the bearer authorization method.",
|
||||
"code": "missing_authorization_header",
|
||||
"type": "auth",
|
||||
"link": "https://docs.meilisearch.com/errors#missing_authorization_header"
|
||||
}
|
||||
)),
|
||||
)
|
||||
)]
|
||||
pub async fn update_documents(
|
||||
index_scheduler: GuardedData<ActionPolicy<{ actions::DOCUMENTS_ADD }>, Data<IndexScheduler>>,
|
||||
index_uid: web::Path<String>,
|
||||
|
@ -742,6 +912,38 @@ async fn copy_body_to_file(
|
|||
Ok(read_file)
|
||||
}
|
||||
|
||||
/// Delete documents
|
||||
///
|
||||
/// Delete a selection of documents based on array of document id's.
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
path = "/{indexUid}/documents",
|
||||
tags = ["Indexes", "Documents"],
|
||||
security(("Bearer" = ["documents.delete", "documents.*", "*"])),
|
||||
params(
|
||||
("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false),
|
||||
),
|
||||
// TODO: how to return an array of strings
|
||||
responses(
|
||||
(status = 200, description = "Task successfully enqueued", body = SummarizedTaskView, content_type = "application/json", example = json!(
|
||||
{
|
||||
"taskUid": 147,
|
||||
"indexUid": null,
|
||||
"status": "enqueued",
|
||||
"type": "documentAdditionOrUpdate",
|
||||
"enqueuedAt": "2024-08-08T17:05:55.791772Z"
|
||||
}
|
||||
)),
|
||||
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
|
||||
{
|
||||
"message": "The Authorization header is missing. It must use the bearer authorization method.",
|
||||
"code": "missing_authorization_header",
|
||||
"type": "auth",
|
||||
"link": "https://docs.meilisearch.com/errors#missing_authorization_header"
|
||||
}
|
||||
)),
|
||||
)
|
||||
)]
|
||||
pub async fn delete_documents_batch(
|
||||
index_scheduler: GuardedData<ActionPolicy<{ actions::DOCUMENTS_DELETE }>, Data<IndexScheduler>>,
|
||||
index_uid: web::Path<String>,
|
||||
|
@ -936,6 +1138,38 @@ pub async fn edit_documents_by_function(
|
|||
Ok(HttpResponse::Accepted().json(task))
|
||||
}
|
||||
|
||||
/// Delete all documents
|
||||
///
|
||||
/// Delete all documents in the specified index.
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
path = "/{indexUid}/documents",
|
||||
tags = ["Indexes", "Documents"],
|
||||
security(("Bearer" = ["documents.delete", "documents.*", "*"])),
|
||||
params(
|
||||
("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false),
|
||||
UpdateDocumentsQuery,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Task successfully enqueued", body = SummarizedTaskView, content_type = "application/json", example = json!(
|
||||
{
|
||||
"taskUid": 147,
|
||||
"indexUid": null,
|
||||
"status": "enqueued",
|
||||
"type": "documentDeletion",
|
||||
"enqueuedAt": "2024-08-08T17:05:55.791772Z"
|
||||
}
|
||||
)),
|
||||
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
|
||||
{
|
||||
"message": "The Authorization header is missing. It must use the bearer authorization method.",
|
||||
"code": "missing_authorization_header",
|
||||
"type": "auth",
|
||||
"link": "https://docs.meilisearch.com/errors#missing_authorization_header"
|
||||
}
|
||||
)),
|
||||
)
|
||||
)]
|
||||
pub async fn clear_all_documents(
|
||||
index_scheduler: GuardedData<ActionPolicy<{ actions::DOCUMENTS_DELETE }>, Data<IndexScheduler>>,
|
||||
index_uid: web::Path<String>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue