mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-12-03 18:15:46 +01:00
Merge #3759
3759: Invalid error code when parsing filters r=dureuill a=irevoire # Pull Request ## Related issue Fixes https://github.com/meilisearch/meilisearch/issues/3753 ## What does this PR do? Fix the error code in case the error comes from the evaluate of the filter for the get, fetch and delete documents routes. Co-authored-by: Tamo <tamo@meilisearch.com>
This commit is contained in:
commit
4d037e6693
@ -24,6 +24,7 @@ use std::io::BufWriter;
|
|||||||
|
|
||||||
use dump::IndexMetadata;
|
use dump::IndexMetadata;
|
||||||
use log::{debug, error, info};
|
use log::{debug, error, info};
|
||||||
|
use meilisearch_types::error::Code;
|
||||||
use meilisearch_types::heed::{RoTxn, RwTxn};
|
use meilisearch_types::heed::{RoTxn, RwTxn};
|
||||||
use meilisearch_types::milli::documents::{obkv_to_object, DocumentsBatchReader};
|
use meilisearch_types::milli::documents::{obkv_to_object, DocumentsBatchReader};
|
||||||
use meilisearch_types::milli::heed::CompactionOption;
|
use meilisearch_types::milli::heed::CompactionOption;
|
||||||
@ -1491,7 +1492,12 @@ fn delete_document_by_filter(filter: &serde_json::Value, index: Index) -> Result
|
|||||||
Ok(if let Some(filter) = filter {
|
Ok(if let Some(filter) = filter {
|
||||||
let mut wtxn = index.write_txn()?;
|
let mut wtxn = index.write_txn()?;
|
||||||
|
|
||||||
let candidates = filter.evaluate(&wtxn, &index)?;
|
let candidates = filter.evaluate(&wtxn, &index).map_err(|err| match err {
|
||||||
|
milli::Error::UserError(milli::UserError::InvalidFilter(_)) => {
|
||||||
|
Error::from(err).with_custom_error_code(Code::InvalidDocumentFilter)
|
||||||
|
}
|
||||||
|
e => e.into(),
|
||||||
|
})?;
|
||||||
let mut delete_operation = DeleteDocuments::new(&mut wtxn, &index)?;
|
let mut delete_operation = DeleteDocuments::new(&mut wtxn, &index)?;
|
||||||
delete_operation.delete_documents(&candidates);
|
delete_operation.delete_documents(&candidates);
|
||||||
let deleted_documents =
|
let deleted_documents =
|
||||||
|
@ -46,6 +46,8 @@ impl From<DateField> for Code {
|
|||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
#[error("{1}")]
|
||||||
|
WithCustomErrorCode(Code, Box<Self>),
|
||||||
#[error("Index `{0}` not found.")]
|
#[error("Index `{0}` not found.")]
|
||||||
IndexNotFound(String),
|
IndexNotFound(String),
|
||||||
#[error("Index `{0}` already exists.")]
|
#[error("Index `{0}` already exists.")]
|
||||||
@ -144,6 +146,7 @@ impl Error {
|
|||||||
pub fn is_recoverable(&self) -> bool {
|
pub fn is_recoverable(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Error::IndexNotFound(_)
|
Error::IndexNotFound(_)
|
||||||
|
| Error::WithCustomErrorCode(_, _)
|
||||||
| Error::IndexAlreadyExists(_)
|
| Error::IndexAlreadyExists(_)
|
||||||
| Error::SwapDuplicateIndexFound(_)
|
| Error::SwapDuplicateIndexFound(_)
|
||||||
| Error::SwapDuplicateIndexesFound(_)
|
| Error::SwapDuplicateIndexesFound(_)
|
||||||
@ -176,11 +179,16 @@ impl Error {
|
|||||||
Error::PlannedFailure => false,
|
Error::PlannedFailure => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_custom_error_code(self, code: Code) -> Self {
|
||||||
|
Self::WithCustomErrorCode(code, Box::new(self))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorCode for Error {
|
impl ErrorCode for Error {
|
||||||
fn error_code(&self) -> Code {
|
fn error_code(&self) -> Code {
|
||||||
match self {
|
match self {
|
||||||
|
Error::WithCustomErrorCode(code, _) => *code,
|
||||||
Error::IndexNotFound(_) => Code::IndexNotFound,
|
Error::IndexNotFound(_) => Code::IndexNotFound,
|
||||||
Error::IndexAlreadyExists(_) => Code::IndexAlreadyExists,
|
Error::IndexAlreadyExists(_) => Code::IndexAlreadyExists,
|
||||||
Error::SwapDuplicateIndexesFound(_) => Code::InvalidSwapDuplicateIndexFound,
|
Error::SwapDuplicateIndexesFound(_) => Code::InvalidSwapDuplicateIndexFound,
|
||||||
|
@ -540,7 +540,12 @@ fn retrieve_documents<S: AsRef<str>>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let candidates = if let Some(filter) = filter {
|
let candidates = if let Some(filter) = filter {
|
||||||
filter.evaluate(&rtxn, index)?
|
filter.evaluate(&rtxn, index).map_err(|err| match err {
|
||||||
|
milli::Error::UserError(milli::UserError::InvalidFilter(_)) => {
|
||||||
|
ResponseError::from_msg(err.to_string(), Code::InvalidDocumentFilter)
|
||||||
|
}
|
||||||
|
e => e.into(),
|
||||||
|
})?
|
||||||
} else {
|
} else {
|
||||||
index.documents_ids(&rtxn)?
|
index.documents_ids(&rtxn)?
|
||||||
};
|
};
|
||||||
|
@ -16,8 +16,11 @@ pub static AUTHORIZATIONS: Lazy<HashMap<(&'static str, &'static str), HashSet<&'
|
|||||||
("GET", "/indexes/products/search") => hashset!{"search", "*"},
|
("GET", "/indexes/products/search") => hashset!{"search", "*"},
|
||||||
("POST", "/indexes/products/documents") => hashset!{"documents.add", "documents.*", "*"},
|
("POST", "/indexes/products/documents") => hashset!{"documents.add", "documents.*", "*"},
|
||||||
("GET", "/indexes/products/documents") => hashset!{"documents.get", "documents.*", "*"},
|
("GET", "/indexes/products/documents") => hashset!{"documents.get", "documents.*", "*"},
|
||||||
|
("POST", "/indexes/products/documents/fetch") => hashset!{"documents.get", "documents.*", "*"},
|
||||||
("GET", "/indexes/products/documents/0") => hashset!{"documents.get", "documents.*", "*"},
|
("GET", "/indexes/products/documents/0") => hashset!{"documents.get", "documents.*", "*"},
|
||||||
("DELETE", "/indexes/products/documents/0") => hashset!{"documents.delete", "documents.*", "*"},
|
("DELETE", "/indexes/products/documents/0") => hashset!{"documents.delete", "documents.*", "*"},
|
||||||
|
("POST", "/indexes/products/documents/delete-batch") => hashset!{"documents.delete", "documents.*", "*"},
|
||||||
|
("POST", "/indexes/products/documents/delete") => hashset!{"documents.delete", "documents.*", "*"},
|
||||||
("GET", "/tasks") => hashset!{"tasks.get", "tasks.*", "*"},
|
("GET", "/tasks") => hashset!{"tasks.get", "tasks.*", "*"},
|
||||||
("DELETE", "/tasks") => hashset!{"tasks.delete", "tasks.*", "*"},
|
("DELETE", "/tasks") => hashset!{"tasks.delete", "tasks.*", "*"},
|
||||||
("GET", "/tasks?indexUid=products") => hashset!{"tasks.get", "tasks.*", "*"},
|
("GET", "/tasks?indexUid=products") => hashset!{"tasks.get", "tasks.*", "*"},
|
||||||
|
@ -180,9 +180,9 @@ async fn get_all_documents_bad_filter() {
|
|||||||
snapshot!(json_string!(response), @r###"
|
snapshot!(json_string!(response), @r###"
|
||||||
{
|
{
|
||||||
"message": "Attribute `doggo` is not filterable. This index does not have configured filterable attributes.\n1:6 doggo=bernese",
|
"message": "Attribute `doggo` is not filterable. This index does not have configured filterable attributes.\n1:6 doggo=bernese",
|
||||||
"code": "invalid_search_filter",
|
"code": "invalid_document_filter",
|
||||||
"type": "invalid_request",
|
"type": "invalid_request",
|
||||||
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
|
"link": "https://docs.meilisearch.com/errors#invalid_document_filter"
|
||||||
}
|
}
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
@ -630,9 +630,9 @@ async fn delete_document_by_filter() {
|
|||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"message": "Attribute `doggo` is not filterable. This index does not have configured filterable attributes.\n1:6 doggo = bernese",
|
"message": "Attribute `doggo` is not filterable. This index does not have configured filterable attributes.\n1:6 doggo = bernese",
|
||||||
"code": "invalid_search_filter",
|
"code": "invalid_document_filter",
|
||||||
"type": "invalid_request",
|
"type": "invalid_request",
|
||||||
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
|
"link": "https://docs.meilisearch.com/errors#invalid_document_filter"
|
||||||
},
|
},
|
||||||
"duration": "[duration]",
|
"duration": "[duration]",
|
||||||
"enqueuedAt": "[date]",
|
"enqueuedAt": "[date]",
|
||||||
@ -664,9 +664,9 @@ async fn delete_document_by_filter() {
|
|||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"message": "Attribute `catto` is not filterable. Available filterable attributes are: `doggo`.\n1:6 catto = jorts",
|
"message": "Attribute `catto` is not filterable. Available filterable attributes are: `doggo`.\n1:6 catto = jorts",
|
||||||
"code": "invalid_search_filter",
|
"code": "invalid_document_filter",
|
||||||
"type": "invalid_request",
|
"type": "invalid_request",
|
||||||
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
|
"link": "https://docs.meilisearch.com/errors#invalid_document_filter"
|
||||||
},
|
},
|
||||||
"duration": "[duration]",
|
"duration": "[duration]",
|
||||||
"enqueuedAt": "[date]",
|
"enqueuedAt": "[date]",
|
||||||
@ -748,4 +748,27 @@ async fn fetch_document_by_filter() {
|
|||||||
"link": "https://docs.meilisearch.com/errors#invalid_document_filter"
|
"link": "https://docs.meilisearch.com/errors#invalid_document_filter"
|
||||||
}
|
}
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
|
let (response, code) = index.get_document_by_filter(json!({ "filter": "cool doggo" })).await;
|
||||||
|
snapshot!(code, @"400 Bad Request");
|
||||||
|
snapshot!(json_string!(response), @r###"
|
||||||
|
{
|
||||||
|
"message": "Was expecting an operation `=`, `!=`, `>=`, `>`, `<=`, `<`, `IN`, `NOT IN`, `TO`, `EXISTS`, `NOT EXISTS`, `IS NULL`, `IS NOT NULL`, `IS EMPTY`, `IS NOT EMPTY`, `_geoRadius`, or `_geoBoundingBox` at `cool doggo`.\n1:11 cool doggo",
|
||||||
|
"code": "invalid_document_filter",
|
||||||
|
"type": "invalid_request",
|
||||||
|
"link": "https://docs.meilisearch.com/errors#invalid_document_filter"
|
||||||
|
}
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let (response, code) =
|
||||||
|
index.get_document_by_filter(json!({ "filter": "doggo = bernese" })).await;
|
||||||
|
snapshot!(code, @"400 Bad Request");
|
||||||
|
snapshot!(json_string!(response), @r###"
|
||||||
|
{
|
||||||
|
"message": "Attribute `doggo` is not filterable. Available filterable attributes are: `color`.\n1:6 doggo = bernese",
|
||||||
|
"code": "invalid_document_filter",
|
||||||
|
"type": "invalid_request",
|
||||||
|
"link": "https://docs.meilisearch.com/errors#invalid_document_filter"
|
||||||
|
}
|
||||||
|
"###);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user