Merge branch 'add-index-name-to-sort-error-message' of github.com:cisco877/meilisearch into add-index-name-to-sort-error-message

This commit is contained in:
Francesco Allara 2024-02-12 20:23:58 +01:00
commit 0f7a004ac9
10 changed files with 42 additions and 19 deletions

View File

@ -634,6 +634,7 @@ impl SearchAggregator {
pub fn from_query(query: &SearchQuery, request: &HttpRequest) -> Self { pub fn from_query(query: &SearchQuery, request: &HttpRequest) -> Self {
let SearchQuery { let SearchQuery {
q, q,
index_uid,
vector, vector,
offset, offset,
limit, limit,

View File

@ -102,6 +102,7 @@ impl From<FacetSearchQuery> for SearchQuery {
SearchQuery { SearchQuery {
q, q,
index_uid: None,
offset: DEFAULT_SEARCH_OFFSET(), offset: DEFAULT_SEARCH_OFFSET(),
limit: DEFAULT_SEARCH_LIMIT(), limit: DEFAULT_SEARCH_LIMIT(),
page: None, page: None,

View File

@ -128,6 +128,7 @@ impl From<SearchQueryGet> for SearchQuery {
}; };
Self { Self {
index_uid: None,
q: other.q, q: other.q,
vector: other.vector.map(CS::into_inner), vector: other.vector.map(CS::into_inner),
offset: other.offset.0, offset: other.offset.0,
@ -203,8 +204,9 @@ pub async fn search_with_url_query(
let distribution = embed(&mut query, index_scheduler.get_ref(), &index).await?; let distribution = embed(&mut query, index_scheduler.get_ref(), &index).await?;
let search_result = let search_result = tokio::task::spawn_blocking(move || {
tokio::task::spawn_blocking(move || perform_search(&index, query, features, distribution)) perform_search(&index, index_uid.to_string(), query, features, distribution)
})
.await?; .await?;
if let Ok(ref search_result) = search_result { if let Ok(ref search_result) = search_result {
aggregate.succeed(search_result); aggregate.succeed(search_result);
@ -242,8 +244,9 @@ pub async fn search_with_post(
let distribution = embed(&mut query, index_scheduler.get_ref(), &index).await?; let distribution = embed(&mut query, index_scheduler.get_ref(), &index).await?;
let search_result = let search_result = tokio::task::spawn_blocking(move || {
tokio::task::spawn_blocking(move || perform_search(&index, query, features, distribution)) perform_search(&index, index_uid.to_string(), query, features, distribution)
})
.await?; .await?;
if let Ok(ref search_result) = search_result { if let Ok(ref search_result) = search_result {
aggregate.succeed(search_result); aggregate.succeed(search_result);

View File

@ -54,6 +54,8 @@ pub async fn multi_search_with_post(
{ {
debug!(on_index = query_index, parameters = ?query, "Multi-search"); debug!(on_index = query_index, parameters = ?query, "Multi-search");
let index_uid_name = &index_uid.clone();
// Check index from API key // Check index from API key
if !index_scheduler.filters().is_index_authorized(&index_uid) { if !index_scheduler.filters().is_index_authorized(&index_uid) {
return Err(AuthenticationError::InvalidToken).with_index(query_index); return Err(AuthenticationError::InvalidToken).with_index(query_index);
@ -80,13 +82,13 @@ pub async fn multi_search_with_post(
.with_index(query_index)?; .with_index(query_index)?;
let search_result = tokio::task::spawn_blocking(move || { let search_result = tokio::task::spawn_blocking(move || {
perform_search(&index, query, features, distribution) perform_search(&index, index_uid.to_string().clone(), query, features, distribution)
}) })
.await .await
.with_index(query_index)?; .with_index(query_index)?;
search_results.push(SearchResultWithIndex { search_results.push(SearchResultWithIndex {
index_uid: index_uid.into_inner(), index_uid: index_uid_name.to_string(),
result: search_result.with_index(query_index)?, result: search_result.with_index(query_index)?,
}); });
} }

View File

@ -41,6 +41,7 @@ pub const DEFAULT_SEMANTIC_RATIO: fn() -> SemanticRatio = || SemanticRatio(0.5);
#[derive(Debug, Clone, Default, PartialEq, Deserr)] #[derive(Debug, Clone, Default, PartialEq, Deserr)]
#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)] #[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)]
pub struct SearchQuery { pub struct SearchQuery {
pub index_uid: Option<String>,
#[deserr(default, error = DeserrJsonError<InvalidSearchQ>)] #[deserr(default, error = DeserrJsonError<InvalidSearchQ>)]
pub q: Option<String>, pub q: Option<String>,
#[deserr(default, error = DeserrJsonError<InvalidSearchVector>)] #[deserr(default, error = DeserrJsonError<InvalidSearchVector>)]
@ -192,6 +193,7 @@ pub struct SearchQueryWithIndex {
impl SearchQueryWithIndex { impl SearchQueryWithIndex {
pub fn into_index_query(self) -> (IndexUid, SearchQuery) { pub fn into_index_query(self) -> (IndexUid, SearchQuery) {
let index_uid_name = self.index_uid.clone().to_string().clone();
let SearchQueryWithIndex { let SearchQueryWithIndex {
index_uid, index_uid,
q, q,
@ -221,6 +223,7 @@ impl SearchQueryWithIndex {
index_uid, index_uid,
SearchQuery { SearchQuery {
q, q,
index_uid: Some(index_uid_name),
vector, vector,
offset, offset,
limit, limit,
@ -378,12 +381,13 @@ pub fn add_search_rules(query: &mut SearchQuery, rules: IndexSearchRules) {
fn prepare_search<'t>( fn prepare_search<'t>(
index: &'t Index, index: &'t Index,
index_uid: &String,
rtxn: &'t RoTxn, rtxn: &'t RoTxn,
query: &'t SearchQuery, query: &'t SearchQuery,
features: RoFeatures, features: RoFeatures,
distribution: Option<DistributionShift>, distribution: Option<DistributionShift>,
) -> Result<(milli::Search<'t>, bool, usize, usize), MeilisearchHttpError> { ) -> Result<(milli::Search<'t>, bool, usize, usize), MeilisearchHttpError> {
let mut search = index.search(rtxn); let mut search = index.search(rtxn, index_uid.clone());
if query.vector.is_some() { if query.vector.is_some() {
features.check_vector("Passing `vector` as a query parameter")?; features.check_vector("Passing `vector` as a query parameter")?;
@ -486,6 +490,7 @@ fn prepare_search<'t>(
pub fn perform_search( pub fn perform_search(
index: &Index, index: &Index,
index_uid: String,
query: SearchQuery, query: SearchQuery,
features: RoFeatures, features: RoFeatures,
distribution: Option<DistributionShift>, distribution: Option<DistributionShift>,
@ -494,7 +499,7 @@ pub fn perform_search(
let rtxn = index.read_txn()?; let rtxn = index.read_txn()?;
let (search, is_finite_pagination, max_total_hits, offset) = let (search, is_finite_pagination, max_total_hits, offset) =
prepare_search(index, &rtxn, &query, features, distribution)?; prepare_search(index, &index_uid, &rtxn, &query, features, distribution)?;
let milli::SearchResult { documents_ids, matching_words, candidates, document_scores, .. } = let milli::SearchResult { documents_ids, matching_words, candidates, document_scores, .. } =
match &query.hybrid { match &query.hybrid {
@ -725,7 +730,8 @@ pub fn perform_facet_search(
let before_search = Instant::now(); let before_search = Instant::now();
let rtxn = index.read_txn()?; let rtxn = index.read_txn()?;
let (search, _, _, _) = prepare_search(index, &rtxn, &search_query, features, None)?; let (search, _, _, _) =
prepare_search(index, &"".to_string(), &rtxn, &search_query, features, None)?;
let mut facet_search = let mut facet_search =
SearchForFacetValues::new(facet_name, search, search_query.hybrid.is_some()); SearchForFacetValues::new(facet_name, search, search_query.hybrid.is_some());
if let Some(facet_query) = &facet_query { if let Some(facet_query) = &facet_query {

View File

@ -122,8 +122,9 @@ only composed of alphanumeric characters (a-z A-Z 0-9), hyphens (-) and undersco
InvalidFilter(String), InvalidFilter(String),
#[error("Invalid type for filter subexpression: expected: {}, found: {1}.", .0.join(", "))] #[error("Invalid type for filter subexpression: expected: {}, found: {1}.", .0.join(", "))]
InvalidFilterExpression(&'static [&'static str], Value), InvalidFilterExpression(&'static [&'static str], Value),
#[error("Attribute `{}` is not sortable. {}", #[error("Attribute `{}` of index `{}` is not sortable. {}",
.field, .field,
.index,
match .valid_fields.is_empty() { match .valid_fields.is_empty() {
true => "This index does not have configured sortable attributes.".to_string(), true => "This index does not have configured sortable attributes.".to_string(),
false => format!("Available sortable attributes are: `{}{}`.", false => format!("Available sortable attributes are: `{}{}`.",
@ -132,7 +133,7 @@ only composed of alphanumeric characters (a-z A-Z 0-9), hyphens (-) and undersco
), ),
} }
)] )]
InvalidSortableAttribute { field: String, valid_fields: BTreeSet<String>, hidden_fields: bool }, InvalidSortableAttribute { field: String, index: String, valid_fields: BTreeSet<String>, hidden_fields: bool },
#[error("Attribute `{}` is not facet-searchable. {}", #[error("Attribute `{}` is not facet-searchable. {}",
.field, .field,
match .valid_fields.is_empty() { match .valid_fields.is_empty() {

View File

@ -1212,8 +1212,8 @@ impl Index {
FacetDistribution::new(rtxn, self) FacetDistribution::new(rtxn, self)
} }
pub fn search<'a>(&'a self, rtxn: &'a RoTxn) -> Search<'a> { pub fn search<'a>(&'a self, rtxn: &'a RoTxn, index_uid: String) -> Search<'a> {
Search::new(rtxn, self) Search::new(rtxn, self, index_uid)
} }
/// Returns the index creation time. /// Returns the index creation time.

View File

@ -115,6 +115,7 @@ impl<'a> Search<'a> {
// TODO: find classier way to achieve that than to reset vector and query params // TODO: find classier way to achieve that than to reset vector and query params
// create separate keyword and semantic searches // create separate keyword and semantic searches
let mut search = Search { let mut search = Search {
index_uid: self.index_uid.to_string().clone(),
query: self.query.clone(), query: self.query.clone(),
vector: self.vector.clone(), vector: self.vector.clone(),
filter: self.filter.clone(), filter: self.filter.clone(),

View File

@ -36,6 +36,7 @@ pub mod hybrid;
pub mod new; pub mod new;
pub struct Search<'a> { pub struct Search<'a> {
index_uid: String,
query: Option<String>, query: Option<String>,
vector: Option<Vec<f32>>, vector: Option<Vec<f32>>,
// this should be linked to the String in the query // this should be linked to the String in the query
@ -57,8 +58,9 @@ pub struct Search<'a> {
} }
impl<'a> Search<'a> { impl<'a> Search<'a> {
pub fn new(rtxn: &'a heed::RoTxn, index: &'a Index) -> Search<'a> { pub fn new(rtxn: &'a heed::RoTxn, index: &'a Index, index_uid: String) -> Search<'a> {
Search { Search {
index_uid,
query: None, query: None,
vector: None, vector: None,
filter: None, filter: None,
@ -156,7 +158,7 @@ impl<'a> Search<'a> {
pub fn execute_for_candidates(&self, has_vector_search: bool) -> Result<RoaringBitmap> { pub fn execute_for_candidates(&self, has_vector_search: bool) -> Result<RoaringBitmap> {
if has_vector_search { if has_vector_search {
let ctx = SearchContext::new(self.index, self.rtxn); let ctx = SearchContext::new(self.index, self.index_uid.to_string(), self.rtxn);
filtered_universe(&ctx, &self.filter) filtered_universe(&ctx, &self.filter)
} else { } else {
Ok(self.execute()?.candidates) Ok(self.execute()?.candidates)
@ -173,7 +175,7 @@ impl<'a> Search<'a> {
} }
}; };
let mut ctx = SearchContext::new(self.index, self.rtxn); let mut ctx = SearchContext::new(self.index, self.index_uid.to_string(), self.rtxn);
if let Some(searchable_attributes) = self.searchable_attributes { if let Some(searchable_attributes) = self.searchable_attributes {
ctx.searchable_attributes(searchable_attributes)?; ctx.searchable_attributes(searchable_attributes)?;
@ -224,6 +226,7 @@ impl<'a> Search<'a> {
impl fmt::Debug for Search<'_> { impl fmt::Debug for Search<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Search { let Search {
index_uid,
query, query,
vector: _, vector: _,
filter, filter,
@ -242,6 +245,7 @@ impl fmt::Debug for Search<'_> {
embedder_name, embedder_name,
} = self; } = self;
f.debug_struct("Search") f.debug_struct("Search")
.field("index_uid", index_uid)
.field("query", query) .field("query", query)
.field("vector", &"[...]") .field("vector", &"[...]")
.field("filter", filter) .field("filter", filter)

View File

@ -58,6 +58,7 @@ use crate::{
/// A structure used throughout the execution of a search query. /// A structure used throughout the execution of a search query.
pub struct SearchContext<'ctx> { pub struct SearchContext<'ctx> {
pub index: &'ctx Index, pub index: &'ctx Index,
pub index_uid: String,
pub txn: &'ctx RoTxn<'ctx>, pub txn: &'ctx RoTxn<'ctx>,
pub db_cache: DatabaseCache<'ctx>, pub db_cache: DatabaseCache<'ctx>,
pub word_interner: DedupInterner<String>, pub word_interner: DedupInterner<String>,
@ -68,9 +69,10 @@ pub struct SearchContext<'ctx> {
} }
impl<'ctx> SearchContext<'ctx> { impl<'ctx> SearchContext<'ctx> {
pub fn new(index: &'ctx Index, txn: &'ctx RoTxn<'ctx>) -> Self { pub fn new(index: &'ctx Index, index_uid: String, txn: &'ctx RoTxn<'ctx>) -> Self {
Self { Self {
index, index,
index_uid,
txn, txn,
db_cache: <_>::default(), db_cache: <_>::default(),
word_interner: <_>::default(), word_interner: <_>::default(),
@ -706,6 +708,7 @@ fn check_sort_criteria(ctx: &SearchContext, sort_criteria: Option<&Vec<AscDesc>>
return Err(UserError::InvalidSortableAttribute { return Err(UserError::InvalidSortableAttribute {
field: field.to_string(), field: field.to_string(),
index: ctx.index_uid.clone(),
valid_fields, valid_fields,
hidden_fields, hidden_fields,
} }
@ -717,6 +720,7 @@ fn check_sort_criteria(ctx: &SearchContext, sort_criteria: Option<&Vec<AscDesc>>
return Err(UserError::InvalidSortableAttribute { return Err(UserError::InvalidSortableAttribute {
field: "_geo".to_string(), field: "_geo".to_string(),
index: ctx.index_uid.clone(),
valid_fields, valid_fields,
hidden_fields, hidden_fields,
} }