mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-01-31 07:23:15 +08:00
Consistent error codes
This commit is contained in:
parent
cb8f033130
commit
de6cd3ac01
@ -243,8 +243,9 @@ InvalidVectorsType , InvalidRequest , BAD_REQUEST ;
|
|||||||
InvalidDocumentId , InvalidRequest , BAD_REQUEST ;
|
InvalidDocumentId , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidDocumentLimit , InvalidRequest , BAD_REQUEST ;
|
InvalidDocumentLimit , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidDocumentOffset , InvalidRequest , BAD_REQUEST ;
|
InvalidDocumentOffset , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidEmbedder , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchEmbedder , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidHybridQuery , InvalidRequest , BAD_REQUEST ;
|
InvalidSimilarEmbedder , InvalidRequest , BAD_REQUEST ;
|
||||||
|
InvalidSearchHybridQuery , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidIndexLimit , InvalidRequest , BAD_REQUEST ;
|
InvalidIndexLimit , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidIndexOffset , InvalidRequest , BAD_REQUEST ;
|
InvalidIndexOffset , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidIndexPrimaryKey , InvalidRequest , BAD_REQUEST ;
|
InvalidIndexPrimaryKey , InvalidRequest , BAD_REQUEST ;
|
||||||
@ -443,7 +444,8 @@ impl ErrorCode for milli::Error {
|
|||||||
UserError::InvalidMinTypoWordLenSetting(_, _) => {
|
UserError::InvalidMinTypoWordLenSetting(_, _) => {
|
||||||
Code::InvalidSettingsTypoTolerance
|
Code::InvalidSettingsTypoTolerance
|
||||||
}
|
}
|
||||||
UserError::InvalidEmbedder(_) => Code::InvalidEmbedder,
|
UserError::InvalidSearchEmbedder(_) => Code::InvalidSearchEmbedder,
|
||||||
|
UserError::InvalidSimilarEmbedder(_) => Code::InvalidSimilarEmbedder,
|
||||||
UserError::VectorEmbeddingError(_) | UserError::DocumentEmbeddingError(_) => {
|
UserError::VectorEmbeddingError(_) | UserError::DocumentEmbeddingError(_) => {
|
||||||
Code::VectorEmbeddingError
|
Code::VectorEmbeddingError
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ pub struct FacetSearchQuery {
|
|||||||
pub q: Option<String>,
|
pub q: Option<String>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchVector>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchVector>)]
|
||||||
pub vector: Option<Vec<f32>>,
|
pub vector: Option<Vec<f32>>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidHybridQuery>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchHybridQuery>)]
|
||||||
pub hybrid: Option<HybridQuery>,
|
pub hybrid: Option<HybridQuery>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchFilter>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchFilter>)]
|
||||||
pub filter: Option<Value>,
|
pub filter: Option<Value>,
|
||||||
|
@ -121,7 +121,7 @@ pub struct SearchQueryGet {
|
|||||||
#[deserr(default, error = DeserrQueryParamError<InvalidSearchAttributesToSearchOn>)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidSearchAttributesToSearchOn>)]
|
||||||
#[param(value_type = Vec<String>, explode = false)]
|
#[param(value_type = Vec<String>, explode = false)]
|
||||||
pub attributes_to_search_on: Option<CS<String>>,
|
pub attributes_to_search_on: Option<CS<String>>,
|
||||||
#[deserr(default, error = DeserrQueryParamError<InvalidEmbedder>)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidSearchEmbedder>)]
|
||||||
pub hybrid_embedder: Option<String>,
|
pub hybrid_embedder: Option<String>,
|
||||||
#[deserr(default, error = DeserrQueryParamError<InvalidSearchSemanticRatio>)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidSearchSemanticRatio>)]
|
||||||
#[param(value_type = f32)]
|
#[param(value_type = f32)]
|
||||||
@ -185,7 +185,7 @@ impl TryFrom<SearchQueryGet> for SearchQuery {
|
|||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
return Err(ResponseError::from_msg(
|
return Err(ResponseError::from_msg(
|
||||||
"`hybridEmbedder` is mandatory when `hybridSemanticRatio` is present".into(),
|
"`hybridEmbedder` is mandatory when `hybridSemanticRatio` is present".into(),
|
||||||
meilisearch_types::error::Code::InvalidHybridQuery,
|
meilisearch_types::error::Code::InvalidSearchHybridQuery,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(Some(embedder), None) => {
|
(Some(embedder), None) => {
|
||||||
|
@ -19,8 +19,8 @@ use crate::extractors::authentication::GuardedData;
|
|||||||
use crate::extractors::sequential_extractor::SeqHandler;
|
use crate::extractors::sequential_extractor::SeqHandler;
|
||||||
use crate::routes::indexes::similar_analytics::{SimilarAggregator, SimilarGET, SimilarPOST};
|
use crate::routes::indexes::similar_analytics::{SimilarAggregator, SimilarGET, SimilarPOST};
|
||||||
use crate::search::{
|
use crate::search::{
|
||||||
add_search_rules, perform_similar, RankingScoreThresholdSimilar, RetrieveVectors, SearchKind,
|
add_search_rules, perform_similar, RankingScoreThresholdSimilar, RetrieveVectors, Route,
|
||||||
SimilarQuery, SimilarResult, DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET,
|
SearchKind, SimilarQuery, SimilarResult, DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(OpenApi)]
|
#[derive(OpenApi)]
|
||||||
@ -235,6 +235,7 @@ async fn similar(
|
|||||||
&index,
|
&index,
|
||||||
&query.embedder,
|
&query.embedder,
|
||||||
None,
|
None,
|
||||||
|
Route::Similar,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
@ -281,7 +282,7 @@ pub struct SimilarQueryGet {
|
|||||||
#[deserr(default, error = DeserrQueryParamError<InvalidSimilarRankingScoreThreshold>, default)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidSimilarRankingScoreThreshold>, default)]
|
||||||
#[param(value_type = Option<f32>)]
|
#[param(value_type = Option<f32>)]
|
||||||
pub ranking_score_threshold: Option<RankingScoreThresholdGet>,
|
pub ranking_score_threshold: Option<RankingScoreThresholdGet>,
|
||||||
#[deserr(error = DeserrQueryParamError<InvalidEmbedder>)]
|
#[deserr(error = DeserrQueryParamError<InvalidSimilarEmbedder>)]
|
||||||
pub embedder: String,
|
pub embedder: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ pub struct SearchQuery {
|
|||||||
pub q: Option<String>,
|
pub q: Option<String>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchVector>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchVector>)]
|
||||||
pub vector: Option<Vec<f32>>,
|
pub vector: Option<Vec<f32>>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidHybridQuery>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchHybridQuery>)]
|
||||||
pub hybrid: Option<HybridQuery>,
|
pub hybrid: Option<HybridQuery>,
|
||||||
#[deserr(default = DEFAULT_SEARCH_OFFSET(), error = DeserrJsonError<InvalidSearchOffset>)]
|
#[deserr(default = DEFAULT_SEARCH_OFFSET(), error = DeserrJsonError<InvalidSearchOffset>)]
|
||||||
#[schema(default = DEFAULT_SEARCH_OFFSET)]
|
#[schema(default = DEFAULT_SEARCH_OFFSET)]
|
||||||
@ -276,12 +276,12 @@ impl fmt::Debug for SearchQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Deserr, ToSchema)]
|
#[derive(Debug, Clone, Default, PartialEq, Deserr, ToSchema)]
|
||||||
#[deserr(error = DeserrJsonError<InvalidHybridQuery>, rename_all = camelCase, deny_unknown_fields)]
|
#[deserr(error = DeserrJsonError<InvalidSearchHybridQuery>, rename_all = camelCase, deny_unknown_fields)]
|
||||||
pub struct HybridQuery {
|
pub struct HybridQuery {
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchSemanticRatio>, default)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchSemanticRatio>, default)]
|
||||||
#[schema(value_type = f32, default)]
|
#[schema(value_type = f32, default)]
|
||||||
pub semantic_ratio: SemanticRatio,
|
pub semantic_ratio: SemanticRatio,
|
||||||
#[deserr(error = DeserrJsonError<InvalidEmbedder>)]
|
#[deserr(error = DeserrJsonError<InvalidSearchEmbedder>)]
|
||||||
pub embedder: String,
|
pub embedder: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,8 +300,14 @@ impl SearchKind {
|
|||||||
embedder_name: &str,
|
embedder_name: &str,
|
||||||
vector_len: Option<usize>,
|
vector_len: Option<usize>,
|
||||||
) -> Result<Self, ResponseError> {
|
) -> Result<Self, ResponseError> {
|
||||||
let (embedder_name, embedder, quantized) =
|
let (embedder_name, embedder, quantized) = Self::embedder(
|
||||||
Self::embedder(index_scheduler, index_uid, index, embedder_name, vector_len)?;
|
index_scheduler,
|
||||||
|
index_uid,
|
||||||
|
index,
|
||||||
|
embedder_name,
|
||||||
|
vector_len,
|
||||||
|
Route::Search,
|
||||||
|
)?;
|
||||||
Ok(Self::SemanticOnly { embedder_name, embedder, quantized })
|
Ok(Self::SemanticOnly { embedder_name, embedder, quantized })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,8 +319,14 @@ impl SearchKind {
|
|||||||
semantic_ratio: f32,
|
semantic_ratio: f32,
|
||||||
vector_len: Option<usize>,
|
vector_len: Option<usize>,
|
||||||
) -> Result<Self, ResponseError> {
|
) -> Result<Self, ResponseError> {
|
||||||
let (embedder_name, embedder, quantized) =
|
let (embedder_name, embedder, quantized) = Self::embedder(
|
||||||
Self::embedder(index_scheduler, index_uid, index, embedder_name, vector_len)?;
|
index_scheduler,
|
||||||
|
index_uid,
|
||||||
|
index,
|
||||||
|
embedder_name,
|
||||||
|
vector_len,
|
||||||
|
Route::Search,
|
||||||
|
)?;
|
||||||
Ok(Self::Hybrid { embedder_name, embedder, quantized, semantic_ratio })
|
Ok(Self::Hybrid { embedder_name, embedder, quantized, semantic_ratio })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,13 +336,21 @@ impl SearchKind {
|
|||||||
index: &Index,
|
index: &Index,
|
||||||
embedder_name: &str,
|
embedder_name: &str,
|
||||||
vector_len: Option<usize>,
|
vector_len: Option<usize>,
|
||||||
|
route: Route,
|
||||||
) -> Result<(String, Arc<Embedder>, bool), ResponseError> {
|
) -> Result<(String, Arc<Embedder>, bool), ResponseError> {
|
||||||
let embedder_configs = index.embedding_configs(&index.read_txn()?)?;
|
let embedder_configs = index.embedding_configs(&index.read_txn()?)?;
|
||||||
let embedders = index_scheduler.embedders(index_uid, embedder_configs)?;
|
let embedders = index_scheduler.embedders(index_uid, embedder_configs)?;
|
||||||
|
|
||||||
let (embedder, _, quantized) = embedders
|
let (embedder, _, quantized) = embedders
|
||||||
.get(embedder_name)
|
.get(embedder_name)
|
||||||
.ok_or(milli::UserError::InvalidEmbedder(embedder_name.to_owned()))
|
.ok_or(match route {
|
||||||
|
Route::Search | Route::MultiSearch => {
|
||||||
|
milli::UserError::InvalidSearchEmbedder(embedder_name.to_owned())
|
||||||
|
}
|
||||||
|
Route::Similar => {
|
||||||
|
milli::UserError::InvalidSimilarEmbedder(embedder_name.to_owned())
|
||||||
|
}
|
||||||
|
})
|
||||||
.map_err(milli::Error::from)?;
|
.map_err(milli::Error::from)?;
|
||||||
|
|
||||||
if let Some(vector_len) = vector_len {
|
if let Some(vector_len) = vector_len {
|
||||||
@ -401,7 +421,7 @@ pub struct SearchQueryWithIndex {
|
|||||||
pub q: Option<String>,
|
pub q: Option<String>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchQ>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchQ>)]
|
||||||
pub vector: Option<Vec<f32>>,
|
pub vector: Option<Vec<f32>>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidHybridQuery>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchHybridQuery>)]
|
||||||
pub hybrid: Option<HybridQuery>,
|
pub hybrid: Option<HybridQuery>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchOffset>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchOffset>)]
|
||||||
pub offset: Option<usize>,
|
pub offset: Option<usize>,
|
||||||
@ -553,7 +573,7 @@ pub struct SimilarQuery {
|
|||||||
pub limit: usize,
|
pub limit: usize,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSimilarFilter>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSimilarFilter>)]
|
||||||
pub filter: Option<Value>,
|
pub filter: Option<Value>,
|
||||||
#[deserr(error = DeserrJsonError<InvalidEmbedder>)]
|
#[deserr(error = DeserrJsonError<InvalidSimilarEmbedder>)]
|
||||||
pub embedder: String,
|
pub embedder: String,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSimilarAttributesToRetrieve>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSimilarAttributesToRetrieve>)]
|
||||||
pub attributes_to_retrieve: Option<BTreeSet<String>>,
|
pub attributes_to_retrieve: Option<BTreeSet<String>>,
|
||||||
@ -1048,9 +1068,10 @@ pub struct ComputedFacets {
|
|||||||
pub stats: BTreeMap<String, FacetStats>,
|
pub stats: BTreeMap<String, FacetStats>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Route {
|
pub enum Route {
|
||||||
Search,
|
Search,
|
||||||
MultiSearch,
|
MultiSearch,
|
||||||
|
Similar,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_facet_distribution_stats<S: AsRef<str>>(
|
fn compute_facet_distribution_stats<S: AsRef<str>>(
|
||||||
|
@ -222,7 +222,9 @@ and can not be more than 511 bytes.", .document_id.to_string()
|
|||||||
#[error("Too many embedders in the configuration. Found {0}, but limited to 256.")]
|
#[error("Too many embedders in the configuration. Found {0}, but limited to 256.")]
|
||||||
TooManyEmbedders(usize),
|
TooManyEmbedders(usize),
|
||||||
#[error("Cannot find embedder with name `{0}`.")]
|
#[error("Cannot find embedder with name `{0}`.")]
|
||||||
InvalidEmbedder(String),
|
InvalidSearchEmbedder(String),
|
||||||
|
#[error("Cannot find embedder with name `{0}`.")]
|
||||||
|
InvalidSimilarEmbedder(String),
|
||||||
#[error("Too many vectors for document with id {0}: found {1}, but limited to 256.")]
|
#[error("Too many vectors for document with id {0}: found {1}, but limited to 256.")]
|
||||||
TooManyVectors(String, usize),
|
TooManyVectors(String, usize),
|
||||||
#[error("`.embedders.{embedder_name}`: Field `{field}` unavailable for source `{source_}` (only available for sources: {}). Available fields: {}",
|
#[error("`.embedders.{embedder_name}`: Field `{field}` unavailable for source `{source_}` (only available for sources: {}). Available fields: {}",
|
||||||
|
@ -32,7 +32,7 @@ impl<Q: RankingRuleQueryTrait> VectorSort<Q> {
|
|||||||
.index
|
.index
|
||||||
.embedder_category_id
|
.embedder_category_id
|
||||||
.get(ctx.txn, embedder_name)?
|
.get(ctx.txn, embedder_name)?
|
||||||
.ok_or_else(|| crate::UserError::InvalidEmbedder(embedder_name.to_owned()))?;
|
.ok_or_else(|| crate::UserError::InvalidSearchEmbedder(embedder_name.to_owned()))?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
query: None,
|
query: None,
|
||||||
|
@ -65,10 +65,9 @@ impl<'a> Similar<'a> {
|
|||||||
let universe = universe;
|
let universe = universe;
|
||||||
|
|
||||||
let embedder_index =
|
let embedder_index =
|
||||||
self.index
|
self.index.embedder_category_id.get(self.rtxn, &self.embedder_name)?.ok_or_else(
|
||||||
.embedder_category_id
|
|| crate::UserError::InvalidSimilarEmbedder(self.embedder_name.to_owned()),
|
||||||
.get(self.rtxn, &self.embedder_name)?
|
)?;
|
||||||
.ok_or_else(|| crate::UserError::InvalidEmbedder(self.embedder_name.to_owned()))?;
|
|
||||||
|
|
||||||
let reader = ArroyWrapper::new(self.index.vector_arroy, embedder_index, self.quantized);
|
let reader = ArroyWrapper::new(self.index.vector_arroy, embedder_index, self.quantized);
|
||||||
let results = reader.nns_by_item(
|
let results = reader.nns_by_item(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user