diff --git a/crates/meilisearch/src/routes/indexes/search.rs b/crates/meilisearch/src/routes/indexes/search.rs index 035ba71d8..697ae9241 100644 --- a/crates/meilisearch/src/routes/indexes/search.rs +++ b/crates/meilisearch/src/routes/indexes/search.rs @@ -483,28 +483,30 @@ pub fn search_kind( index_uid: String, index: &milli::Index, ) -> Result { + let is_placeholder_query = + if let Some(q) = query.q.as_deref() { q.trim().is_empty() } else { true }; + let non_placeholder_query = !is_placeholder_query; + let is_media = query.media.is_some(); // handle with care, the order of cases matters, the semantics is subtle - match (query.q.as_deref(), &query.hybrid, query.vector.as_deref()) { - // empty query, no vector => placeholder search - (Some(q), _, None) if q.trim().is_empty() => Ok(SearchKind::KeywordOnly), - // no query, no vector => placeholder search - (None, _, None) => Ok(SearchKind::KeywordOnly), - // hybrid.semantic_ratio == 1.0 => vector - (_, Some(HybridQuery { semantic_ratio, embedder }), v) if **semantic_ratio == 1.0 => { - SearchKind::semantic(index_scheduler, index_uid, index, embedder, v.map(|v| v.len())) - } - // hybrid.semantic_ratio == 0.0 => keyword - (_, Some(HybridQuery { semantic_ratio, embedder: _ }), _) if **semantic_ratio == 0.0 => { + match (is_media, non_placeholder_query, &query.hybrid, query.vector.as_deref()) { + // media + vector => error + (true, _, _, Some(_)) => Err(MeilisearchHttpError::MediaAndVector.into()), + // media + !hybrid => error + (true, _, None, _) => Err(MeilisearchHttpError::MissingSearchHybrid.into()), + // vector + !hybrid => error + (_, _, None, Some(_)) => Err(MeilisearchHttpError::MissingSearchHybrid.into()), + // hybrid S0 => keyword + (_, _, Some(HybridQuery { semantic_ratio, embedder: _ }), _) if **semantic_ratio == 0.0 => { Ok(SearchKind::KeywordOnly) } - // no query, hybrid, vector => semantic - (None, Some(HybridQuery { semantic_ratio: _, embedder }), Some(v)) => { - SearchKind::semantic(index_scheduler, index_uid, index, embedder, Some(v.len())) + // !q + !vector => placeholder search + (false, false, _, None) => Ok(SearchKind::KeywordOnly), + // hybrid S100 => semantic + (_, _, Some(HybridQuery { semantic_ratio, embedder }), v) if **semantic_ratio == 1.0 => { + SearchKind::semantic(index_scheduler, index_uid, index, embedder, v.map(|v| v.len())) } - // query, no hybrid, no vector => keyword - (Some(_), None, None) => Ok(SearchKind::KeywordOnly), - // query, hybrid, maybe vector => hybrid - (Some(_), Some(HybridQuery { semantic_ratio, embedder }), v) => SearchKind::hybrid( + // q + hybrid => hybrid + (_, true, Some(HybridQuery { semantic_ratio, embedder }), v) => SearchKind::hybrid( index_scheduler, index_uid, index, @@ -512,7 +514,11 @@ pub fn search_kind( **semantic_ratio, v.map(|v| v.len()), ), - - (_, None, Some(_)) => Err(MeilisearchHttpError::MissingSearchHybrid.into()), + // !q + hybrid => semantic + (_, false, Some(HybridQuery { semantic_ratio: _, embedder }), v) => { + SearchKind::semantic(index_scheduler, index_uid, index, embedder, v.map(|v| v.len())) + } + // q => keyword + (false, true, None, None) => Ok(SearchKind::KeywordOnly), } }