mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-22 21:04:27 +01:00
Add ranking score threshold to similar API
This commit is contained in:
parent
4f03b0cf5b
commit
7ce2691374
@ -190,4 +190,5 @@ merge_with_error_impl_take_error_message!(ParseTaskStatusError);
|
|||||||
merge_with_error_impl_take_error_message!(IndexUidFormatError);
|
merge_with_error_impl_take_error_message!(IndexUidFormatError);
|
||||||
merge_with_error_impl_take_error_message!(InvalidSearchSemanticRatio);
|
merge_with_error_impl_take_error_message!(InvalidSearchSemanticRatio);
|
||||||
merge_with_error_impl_take_error_message!(InvalidSearchRankingScoreThreshold);
|
merge_with_error_impl_take_error_message!(InvalidSearchRankingScoreThreshold);
|
||||||
|
merge_with_error_impl_take_error_message!(InvalidSimilarRankingScoreThreshold);
|
||||||
merge_with_error_impl_take_error_message!(InvalidSimilarId);
|
merge_with_error_impl_take_error_message!(InvalidSimilarId);
|
||||||
|
@ -242,6 +242,7 @@ InvalidSearchAttributesToHighlight , InvalidRequest , BAD_REQUEST ;
|
|||||||
InvalidSimilarAttributesToRetrieve , InvalidRequest , BAD_REQUEST ;
|
InvalidSimilarAttributesToRetrieve , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchAttributesToRetrieve , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchAttributesToRetrieve , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchRankingScoreThreshold , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchRankingScoreThreshold , InvalidRequest , BAD_REQUEST ;
|
||||||
|
InvalidSimilarRankingScoreThreshold , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchCropLength , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchCropLength , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchCropMarker , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchCropMarker , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchFacets , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchFacets , InvalidRequest , BAD_REQUEST ;
|
||||||
@ -515,6 +516,12 @@ impl fmt::Display for deserr_codes::InvalidSearchRankingScoreThreshold {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for deserr_codes::InvalidSimilarRankingScoreThreshold {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
deserr_codes::InvalidSearchRankingScoreThreshold.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! internal_error {
|
macro_rules! internal_error {
|
||||||
($target:ty : $($other:path), *) => {
|
($target:ty : $($other:path), *) => {
|
||||||
|
@ -6,8 +6,8 @@ use meilisearch_types::deserr::query_params::Param;
|
|||||||
use meilisearch_types::deserr::{DeserrJsonError, DeserrQueryParamError};
|
use meilisearch_types::deserr::{DeserrJsonError, DeserrQueryParamError};
|
||||||
use meilisearch_types::error::deserr_codes::{
|
use meilisearch_types::error::deserr_codes::{
|
||||||
InvalidEmbedder, InvalidSimilarAttributesToRetrieve, InvalidSimilarFilter, InvalidSimilarId,
|
InvalidEmbedder, InvalidSimilarAttributesToRetrieve, InvalidSimilarFilter, InvalidSimilarId,
|
||||||
InvalidSimilarLimit, InvalidSimilarOffset, InvalidSimilarShowRankingScore,
|
InvalidSimilarLimit, InvalidSimilarOffset, InvalidSimilarRankingScoreThreshold,
|
||||||
InvalidSimilarShowRankingScoreDetails,
|
InvalidSimilarShowRankingScore, InvalidSimilarShowRankingScoreDetails,
|
||||||
};
|
};
|
||||||
use meilisearch_types::error::{ErrorCode as _, ResponseError};
|
use meilisearch_types::error::{ErrorCode as _, ResponseError};
|
||||||
use meilisearch_types::index_uid::IndexUid;
|
use meilisearch_types::index_uid::IndexUid;
|
||||||
@ -21,8 +21,8 @@ use crate::analytics::{Analytics, SimilarAggregator};
|
|||||||
use crate::extractors::authentication::GuardedData;
|
use crate::extractors::authentication::GuardedData;
|
||||||
use crate::extractors::sequential_extractor::SeqHandler;
|
use crate::extractors::sequential_extractor::SeqHandler;
|
||||||
use crate::search::{
|
use crate::search::{
|
||||||
add_search_rules, perform_similar, SearchKind, SimilarQuery, SimilarResult,
|
add_search_rules, perform_similar, RankingScoreThresholdSimilar, SearchKind, SimilarQuery,
|
||||||
DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET,
|
SimilarResult, DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn configure(cfg: &mut web::ServiceConfig) {
|
pub fn configure(cfg: &mut web::ServiceConfig) {
|
||||||
@ -42,9 +42,7 @@ pub async fn similar_get(
|
|||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let index_uid = IndexUid::try_from(index_uid.into_inner())?;
|
let index_uid = IndexUid::try_from(index_uid.into_inner())?;
|
||||||
|
|
||||||
let query = params.0.try_into().map_err(|code: InvalidSimilarId| {
|
let query = params.0.try_into()?;
|
||||||
ResponseError::from_msg(code.to_string(), code.error_code())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let mut aggregate = SimilarAggregator::from_query(&query, &req);
|
let mut aggregate = SimilarAggregator::from_query(&query, &req);
|
||||||
|
|
||||||
@ -130,12 +128,27 @@ pub struct SimilarQueryGet {
|
|||||||
show_ranking_score: Param<bool>,
|
show_ranking_score: Param<bool>,
|
||||||
#[deserr(default, error = DeserrQueryParamError<InvalidSimilarShowRankingScoreDetails>)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidSimilarShowRankingScoreDetails>)]
|
||||||
show_ranking_score_details: Param<bool>,
|
show_ranking_score_details: Param<bool>,
|
||||||
|
#[deserr(default, error = DeserrQueryParamError<InvalidSimilarRankingScoreThreshold>, default)]
|
||||||
|
pub ranking_score_threshold: Option<RankingScoreThresholdGet>,
|
||||||
#[deserr(default, error = DeserrQueryParamError<InvalidEmbedder>)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidEmbedder>)]
|
||||||
pub embedder: Option<String>,
|
pub embedder: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, deserr::Deserr)]
|
||||||
|
#[deserr(try_from(String) = TryFrom::try_from -> InvalidSimilarRankingScoreThreshold)]
|
||||||
|
pub struct RankingScoreThresholdGet(RankingScoreThresholdSimilar);
|
||||||
|
|
||||||
|
impl std::convert::TryFrom<String> for RankingScoreThresholdGet {
|
||||||
|
type Error = InvalidSimilarRankingScoreThreshold;
|
||||||
|
|
||||||
|
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||||
|
let f: f64 = s.parse().map_err(|_| InvalidSimilarRankingScoreThreshold)?;
|
||||||
|
Ok(RankingScoreThresholdGet(RankingScoreThresholdSimilar::try_from(f)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<SimilarQueryGet> for SimilarQuery {
|
impl TryFrom<SimilarQueryGet> for SimilarQuery {
|
||||||
type Error = InvalidSimilarId;
|
type Error = ResponseError;
|
||||||
|
|
||||||
fn try_from(
|
fn try_from(
|
||||||
SimilarQueryGet {
|
SimilarQueryGet {
|
||||||
@ -147,6 +160,7 @@ impl TryFrom<SimilarQueryGet> for SimilarQuery {
|
|||||||
show_ranking_score,
|
show_ranking_score,
|
||||||
show_ranking_score_details,
|
show_ranking_score_details,
|
||||||
embedder,
|
embedder,
|
||||||
|
ranking_score_threshold,
|
||||||
}: SimilarQueryGet,
|
}: SimilarQueryGet,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let filter = match filter {
|
let filter = match filter {
|
||||||
@ -158,7 +172,9 @@ impl TryFrom<SimilarQueryGet> for SimilarQuery {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(SimilarQuery {
|
Ok(SimilarQuery {
|
||||||
id: id.0.try_into()?,
|
id: id.0.try_into().map_err(|code: InvalidSimilarId| {
|
||||||
|
ResponseError::from_msg(code.to_string(), code.error_code())
|
||||||
|
})?,
|
||||||
offset: offset.0,
|
offset: offset.0,
|
||||||
limit: limit.0,
|
limit: limit.0,
|
||||||
filter,
|
filter,
|
||||||
@ -166,6 +182,7 @@ impl TryFrom<SimilarQueryGet> for SimilarQuery {
|
|||||||
attributes_to_retrieve: attributes_to_retrieve.map(|o| o.into_iter().collect()),
|
attributes_to_retrieve: attributes_to_retrieve.map(|o| o.into_iter().collect()),
|
||||||
show_ranking_score: show_ranking_score.0,
|
show_ranking_score: show_ranking_score.0,
|
||||||
show_ranking_score_details: show_ranking_score_details.0,
|
show_ranking_score_details: show_ranking_score_details.0,
|
||||||
|
ranking_score_threshold: ranking_score_threshold.map(|x| x.0),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,24 @@ impl std::convert::TryFrom<f64> for RankingScoreThreshold {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Deserr)]
|
||||||
|
#[deserr(try_from(f64) = TryFrom::try_from -> InvalidSimilarRankingScoreThreshold)]
|
||||||
|
pub struct RankingScoreThresholdSimilar(f64);
|
||||||
|
|
||||||
|
impl std::convert::TryFrom<f64> for RankingScoreThresholdSimilar {
|
||||||
|
type Error = InvalidSimilarRankingScoreThreshold;
|
||||||
|
|
||||||
|
fn try_from(f: f64) -> Result<Self, Self::Error> {
|
||||||
|
// the suggested "fix" is: `!(0.0..=1.0).contains(&f)`` which is allegedly less readable
|
||||||
|
#[allow(clippy::manual_range_contains)]
|
||||||
|
if f > 1.0 || f < 0.0 {
|
||||||
|
Err(InvalidSimilarRankingScoreThreshold)
|
||||||
|
} else {
|
||||||
|
Ok(Self(f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Since this structure is logged A LOT we're going to reduce the number of things it logs to the bare minimum.
|
// Since this structure is logged A LOT we're going to reduce the number of things it logs to the bare minimum.
|
||||||
// - Only what IS used, we know everything else is set to None so there is no need to print it
|
// - Only what IS used, we know everything else is set to None so there is no need to print it
|
||||||
// - Re-order the most important field to debug first
|
// - Re-order the most important field to debug first
|
||||||
@ -464,6 +482,8 @@ pub struct SimilarQuery {
|
|||||||
pub show_ranking_score: bool,
|
pub show_ranking_score: bool,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSimilarShowRankingScoreDetails>, default)]
|
#[deserr(default, error = DeserrJsonError<InvalidSimilarShowRankingScoreDetails>, default)]
|
||||||
pub show_ranking_score_details: bool,
|
pub show_ranking_score_details: bool,
|
||||||
|
#[deserr(default, error = DeserrJsonError<InvalidSimilarRankingScoreThreshold>, default)]
|
||||||
|
pub ranking_score_threshold: Option<RankingScoreThresholdSimilar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Deserr)]
|
#[derive(Debug, Clone, PartialEq, Deserr)]
|
||||||
@ -1102,6 +1122,7 @@ pub fn perform_similar(
|
|||||||
attributes_to_retrieve,
|
attributes_to_retrieve,
|
||||||
show_ranking_score,
|
show_ranking_score,
|
||||||
show_ranking_score_details,
|
show_ranking_score_details,
|
||||||
|
ranking_score_threshold,
|
||||||
} = query;
|
} = query;
|
||||||
|
|
||||||
// using let-else rather than `?` so that the borrow checker identifies we're always returning here,
|
// using let-else rather than `?` so that the borrow checker identifies we're always returning here,
|
||||||
@ -1125,6 +1146,10 @@ pub fn perform_similar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ranking_score_threshold) = ranking_score_threshold {
|
||||||
|
similar.ranking_score_threshold(ranking_score_threshold.0);
|
||||||
|
}
|
||||||
|
|
||||||
let milli::SearchResult {
|
let milli::SearchResult {
|
||||||
documents_ids,
|
documents_ids,
|
||||||
matching_words: _,
|
matching_words: _,
|
||||||
|
Loading…
Reference in New Issue
Block a user