mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-09-06 12:46:31 +00:00
refactor: rename personalization API fields and move checks inside service
- Rename 'personalization' field to 'personalize' in API - Rename 'userProfile' to 'userContext' in personalization object - Remove 'personalized' boolean field (activation now based on non-null 'personalize') - Move personalization checks inside rerank_search_results function - Use 'let else' pattern for better error handling - Update error types and messages to reflect new field names - Update all search routes and analytics to use new field names
This commit is contained in:
@ -308,9 +308,8 @@ InvalidSearchShowRankingScoreDetails , InvalidRequest , BAD_REQU
|
|||||||
InvalidSimilarShowRankingScoreDetails , InvalidRequest , BAD_REQUEST ;
|
InvalidSimilarShowRankingScoreDetails , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchSort , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchSort , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchDistinct , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchDistinct , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchPersonalization , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchPersonalize , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchPersonalizationPersonalized , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchPersonalizeUserContext , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSearchPersonalizationUserProfile , InvalidRequest , BAD_REQUEST ;
|
|
||||||
InvalidSearchMediaAndVector , InvalidRequest , BAD_REQUEST ;
|
InvalidSearchMediaAndVector , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSettingsDisplayedAttributes , InvalidRequest , BAD_REQUEST ;
|
InvalidSettingsDisplayedAttributes , InvalidRequest , BAD_REQUEST ;
|
||||||
InvalidSettingsDistinctAttribute , InvalidRequest , BAD_REQUEST ;
|
InvalidSettingsDistinctAttribute , InvalidRequest , BAD_REQUEST ;
|
||||||
@ -640,21 +639,15 @@ impl fmt::Display for deserr_codes::InvalidNetworkSearchApiKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for deserr_codes::InvalidSearchPersonalization {
|
impl fmt::Display for deserr_codes::InvalidSearchPersonalize {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "the value of `personalization` is invalid, expected a JSON object with `personalized` boolean and optional `userProfile` string.")
|
write!(f, "the value of `personalize` is invalid, expected a JSON object with optional `userContext` string.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for deserr_codes::InvalidSearchPersonalizationPersonalized {
|
impl fmt::Display for deserr_codes::InvalidSearchPersonalizeUserContext {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "the value of `personalized` is invalid, expected a boolean.")
|
write!(f, "the value of `userContext` is invalid, expected a string.")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for deserr_codes::InvalidSearchPersonalizationUserProfile {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "the value of `userProfile` is invalid, expected a string.")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::search::{Personalization, SearchResult};
|
use crate::search::{Personalize, SearchResult};
|
||||||
use cohere_rust::{
|
use cohere_rust::{
|
||||||
api::rerank::{ReRankModel, ReRankRequest},
|
api::rerank::{ReRankModel, ReRankRequest},
|
||||||
Cohere,
|
Cohere,
|
||||||
@ -26,15 +26,13 @@ impl PersonalizationService {
|
|||||||
pub async fn rerank_search_results(
|
pub async fn rerank_search_results(
|
||||||
&self,
|
&self,
|
||||||
search_result: SearchResult,
|
search_result: SearchResult,
|
||||||
personalization: &Personalization,
|
personalize: Option<&Personalize>,
|
||||||
query: &str,
|
query: Option<&str>,
|
||||||
) -> Result<SearchResult, ResponseError> {
|
) -> Result<SearchResult, ResponseError> {
|
||||||
// If personalization is not enabled or no API key, return original results
|
// If personalization is not requested, no API key, or no query, return original results
|
||||||
if !personalization.personalized || self.cohere.is_none() {
|
let Some(_personalize) = personalize else { return Ok(search_result) };
|
||||||
return Ok(search_result);
|
let Some(cohere) = &self.cohere else { return Ok(search_result) };
|
||||||
}
|
let Some(query) = query else { return Ok(search_result) };
|
||||||
|
|
||||||
let cohere = self.cohere.as_ref().unwrap();
|
|
||||||
|
|
||||||
// Extract documents for reranking
|
// Extract documents for reranking
|
||||||
let documents: Vec<String> = search_result
|
let documents: Vec<String> = search_result
|
||||||
@ -95,8 +93,7 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_personalization_service_without_api_key() {
|
async fn test_personalization_service_without_api_key() {
|
||||||
let service = PersonalizationService::new(None);
|
let service = PersonalizationService::new(None);
|
||||||
let personalization =
|
let personalize = Personalize { user_context: Some("test user".to_string()) };
|
||||||
Personalization { personalized: true, user_profile: Some("test user".to_string()) };
|
|
||||||
|
|
||||||
let search_result = SearchResult {
|
let search_result = SearchResult {
|
||||||
hits: vec![SearchHit {
|
hits: vec![SearchHit {
|
||||||
@ -116,8 +113,9 @@ mod tests {
|
|||||||
used_negative_operator: false,
|
used_negative_operator: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result =
|
let result = service
|
||||||
service.rerank_search_results(search_result.clone(), &personalization, "test").await;
|
.rerank_search_results(search_result.clone(), Some(&personalize), Some("test"))
|
||||||
|
.await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
// Should return original results when no API key is provided
|
// Should return original results when no API key is provided
|
||||||
@ -128,10 +126,7 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_personalization_service_disabled() {
|
async fn test_personalization_service_disabled() {
|
||||||
let service = PersonalizationService::new(Some("fake_key".to_string()));
|
let service = PersonalizationService::new(Some("fake_key".to_string()));
|
||||||
let personalization = Personalization {
|
let personalize = Personalize { user_context: Some("test user".to_string()) };
|
||||||
personalized: false, // Personalization disabled
|
|
||||||
user_profile: Some("test user".to_string()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let search_result = SearchResult {
|
let search_result = SearchResult {
|
||||||
hits: vec![SearchHit {
|
hits: vec![SearchHit {
|
||||||
@ -151,8 +146,9 @@ mod tests {
|
|||||||
used_negative_operator: false,
|
used_negative_operator: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result =
|
let result = service
|
||||||
service.rerank_search_results(search_result.clone(), &personalization, "test").await;
|
.rerank_search_results(search_result.clone(), Some(&personalize), Some("test"))
|
||||||
|
.await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
// Should return original results when personalization is disabled
|
// Should return original results when personalization is disabled
|
||||||
|
@ -337,7 +337,7 @@ impl From<FacetSearchQuery> for SearchQuery {
|
|||||||
hybrid,
|
hybrid,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
personalization: None,
|
personalize: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ use crate::extractors::sequential_extractor::SeqHandler;
|
|||||||
use crate::metrics::MEILISEARCH_DEGRADED_SEARCH_REQUESTS;
|
use crate::metrics::MEILISEARCH_DEGRADED_SEARCH_REQUESTS;
|
||||||
use crate::routes::indexes::search_analytics::{SearchAggregator, SearchGET, SearchPOST};
|
use crate::routes::indexes::search_analytics::{SearchAggregator, SearchGET, SearchPOST};
|
||||||
use crate::search::{
|
use crate::search::{
|
||||||
add_search_rules, perform_search, HybridQuery, MatchingStrategy, Personalization,
|
add_search_rules, perform_search, HybridQuery, MatchingStrategy, Personalize,
|
||||||
RankingScoreThreshold, RetrieveVectors, SearchKind, SearchQuery, SearchResult, SemanticRatio,
|
RankingScoreThreshold, RetrieveVectors, SearchKind, SearchQuery, SearchResult, SemanticRatio,
|
||||||
DEFAULT_CROP_LENGTH, DEFAULT_CROP_MARKER, DEFAULT_HIGHLIGHT_POST_TAG,
|
DEFAULT_CROP_LENGTH, DEFAULT_CROP_MARKER, DEFAULT_HIGHLIGHT_POST_TAG,
|
||||||
DEFAULT_HIGHLIGHT_PRE_TAG, DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET, DEFAULT_SEMANTIC_RATIO,
|
DEFAULT_HIGHLIGHT_PRE_TAG, DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET, DEFAULT_SEMANTIC_RATIO,
|
||||||
@ -132,11 +132,8 @@ pub struct SearchQueryGet {
|
|||||||
#[deserr(default, error = DeserrQueryParamError<InvalidSearchLocales>)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidSearchLocales>)]
|
||||||
#[param(value_type = Vec<Locale>, explode = false)]
|
#[param(value_type = Vec<Locale>, explode = false)]
|
||||||
pub locales: Option<CS<Locale>>,
|
pub locales: Option<CS<Locale>>,
|
||||||
#[deserr(default, error = DeserrQueryParamError<InvalidSearchPersonalizationPersonalized>)]
|
#[deserr(default, error = DeserrQueryParamError<InvalidSearchPersonalizeUserContext>)]
|
||||||
#[param(value_type = bool)]
|
pub personalize_user_context: Option<String>,
|
||||||
pub personalization_personalized: Option<bool>,
|
|
||||||
#[deserr(default, error = DeserrQueryParamError<InvalidSearchPersonalizationUserProfile>)]
|
|
||||||
pub personalization_user_profile: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, deserr::Deserr)]
|
#[derive(Debug, Clone, Copy, PartialEq, deserr::Deserr)]
|
||||||
@ -208,21 +205,9 @@ impl TryFrom<SearchQueryGet> for SearchQuery {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let personalization = match (
|
let personalize = other
|
||||||
other.personalization_personalized,
|
.personalize_user_context
|
||||||
other.personalization_user_profile,
|
.map(|user_context| Personalize { user_context: Some(user_context) });
|
||||||
) {
|
|
||||||
(None, None) => None,
|
|
||||||
(Some(personalized), user_profile) => {
|
|
||||||
Some(Personalization { personalized, user_profile })
|
|
||||||
}
|
|
||||||
(None, Some(_)) => {
|
|
||||||
return Err(ResponseError::from_msg(
|
|
||||||
"`personalizationPersonalized` is mandatory when `personalizationUserProfile` is present".into(),
|
|
||||||
meilisearch_types::error::Code::InvalidSearchPersonalization,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
q: other.q,
|
q: other.q,
|
||||||
@ -251,7 +236,7 @@ impl TryFrom<SearchQueryGet> for SearchQuery {
|
|||||||
hybrid,
|
hybrid,
|
||||||
ranking_score_threshold: other.ranking_score_threshold.map(|o| o.0),
|
ranking_score_threshold: other.ranking_score_threshold.map(|o| o.0),
|
||||||
locales: other.locales.map(|o| o.into_iter().collect()),
|
locales: other.locales.map(|o| o.into_iter().collect()),
|
||||||
personalization,
|
personalize,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,7 +350,7 @@ pub async fn search_with_url_query(
|
|||||||
let retrieve_vector = RetrieveVectors::new(query.retrieve_vectors);
|
let retrieve_vector = RetrieveVectors::new(query.retrieve_vectors);
|
||||||
|
|
||||||
// Extract personalization and query string before moving query
|
// Extract personalization and query string before moving query
|
||||||
let personalization = query.personalization.clone();
|
let personalize = query.personalize.clone();
|
||||||
let query_str = query.q.clone();
|
let query_str = query.q.clone();
|
||||||
|
|
||||||
let permit = search_queue.try_get_search_permit().await?;
|
let permit = search_queue.try_get_search_permit().await?;
|
||||||
@ -390,13 +375,9 @@ pub async fn search_with_url_query(
|
|||||||
let mut search_result = search_result?;
|
let mut search_result = search_result?;
|
||||||
|
|
||||||
// Apply personalization if requested
|
// Apply personalization if requested
|
||||||
if let Some(personalization) = &personalization {
|
search_result = personalization_service
|
||||||
if let Some(query_str) = &query_str {
|
.rerank_search_results(search_result, personalize.as_ref(), query_str.as_deref())
|
||||||
search_result = personalization_service
|
.await?;
|
||||||
.rerank_search_results(search_result, personalization, query_str)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(returns = ?search_result, "Search get");
|
debug!(returns = ?search_result, "Search get");
|
||||||
Ok(HttpResponse::Ok().json(search_result))
|
Ok(HttpResponse::Ok().json(search_result))
|
||||||
@ -486,7 +467,7 @@ pub async fn search_with_post(
|
|||||||
let retrieve_vectors = RetrieveVectors::new(query.retrieve_vectors);
|
let retrieve_vectors = RetrieveVectors::new(query.retrieve_vectors);
|
||||||
|
|
||||||
// Extract personalization and query string before moving query
|
// Extract personalization and query string before moving query
|
||||||
let personalization = query.personalization.clone();
|
let personalize = query.personalize.clone();
|
||||||
let query_str = query.q.clone();
|
let query_str = query.q.clone();
|
||||||
|
|
||||||
let permit = search_queue.try_get_search_permit().await?;
|
let permit = search_queue.try_get_search_permit().await?;
|
||||||
@ -514,13 +495,9 @@ pub async fn search_with_post(
|
|||||||
let mut search_result = search_result?;
|
let mut search_result = search_result?;
|
||||||
|
|
||||||
// Apply personalization if requested
|
// Apply personalization if requested
|
||||||
if let Some(personalization) = &personalization {
|
search_result = personalization_service
|
||||||
if let Some(query_str) = &query_str {
|
.rerank_search_results(search_result, personalize.as_ref(), query_str.as_deref())
|
||||||
search_result = personalization_service
|
.await?;
|
||||||
.rerank_search_results(search_result, personalization, query_str)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(returns = ?search_result, "Search post");
|
debug!(returns = ?search_result, "Search post");
|
||||||
Ok(HttpResponse::Ok().json(search_result))
|
Ok(HttpResponse::Ok().json(search_result))
|
||||||
|
@ -125,7 +125,7 @@ impl<Method: AggregateMethod> SearchAggregator<Method> {
|
|||||||
hybrid,
|
hybrid,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
personalization: _,
|
personalize: _,
|
||||||
} = query;
|
} = query;
|
||||||
|
|
||||||
let mut ret = Self::default();
|
let mut ret = Self::default();
|
||||||
|
@ -66,7 +66,7 @@ impl MultiSearchAggregator {
|
|||||||
hybrid: _,
|
hybrid: _,
|
||||||
ranking_score_threshold: _,
|
ranking_score_threshold: _,
|
||||||
locales: _,
|
locales: _,
|
||||||
personalization: _,
|
personalize: _,
|
||||||
} in &federated_search.queries
|
} in &federated_search.queries
|
||||||
{
|
{
|
||||||
if let Some(federation_options) = federation_options {
|
if let Some(federation_options) = federation_options {
|
||||||
|
@ -58,12 +58,10 @@ pub const DEFAULT_HIGHLIGHT_POST_TAG: fn() -> String = || "</em>".to_string();
|
|||||||
pub const DEFAULT_SEMANTIC_RATIO: fn() -> SemanticRatio = || SemanticRatio(0.5);
|
pub const DEFAULT_SEMANTIC_RATIO: fn() -> SemanticRatio = || SemanticRatio(0.5);
|
||||||
|
|
||||||
#[derive(Clone, Default, PartialEq, Deserr, ToSchema, Debug)]
|
#[derive(Clone, Default, PartialEq, Deserr, ToSchema, Debug)]
|
||||||
#[deserr(error = DeserrJsonError<InvalidSearchPersonalization>, rename_all = camelCase, deny_unknown_fields)]
|
#[deserr(error = DeserrJsonError<InvalidSearchPersonalize>, rename_all = camelCase, deny_unknown_fields)]
|
||||||
pub struct Personalization {
|
pub struct Personalize {
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchPersonalizationPersonalized>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchPersonalizeUserContext>)]
|
||||||
pub personalized: bool,
|
pub user_context: Option<String>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchPersonalizationUserProfile>)]
|
|
||||||
pub user_profile: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, PartialEq, Deserr, ToSchema)]
|
#[derive(Clone, Default, PartialEq, Deserr, ToSchema)]
|
||||||
@ -127,8 +125,8 @@ pub struct SearchQuery {
|
|||||||
pub ranking_score_threshold: Option<RankingScoreThreshold>,
|
pub ranking_score_threshold: Option<RankingScoreThreshold>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchLocales>)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchLocales>)]
|
||||||
pub locales: Option<Vec<Locale>>,
|
pub locales: Option<Vec<Locale>>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchPersonalization>, default)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchPersonalize>, default)]
|
||||||
pub personalization: Option<Personalization>,
|
pub personalize: Option<Personalize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SearchParameters> for SearchQuery {
|
impl From<SearchParameters> for SearchQuery {
|
||||||
@ -175,7 +173,7 @@ impl From<SearchParameters> for SearchQuery {
|
|||||||
highlight_post_tag: DEFAULT_HIGHLIGHT_POST_TAG(),
|
highlight_post_tag: DEFAULT_HIGHLIGHT_POST_TAG(),
|
||||||
crop_marker: DEFAULT_CROP_MARKER(),
|
crop_marker: DEFAULT_CROP_MARKER(),
|
||||||
locales: None,
|
locales: None,
|
||||||
personalization: None,
|
personalize: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,7 +254,7 @@ impl fmt::Debug for SearchQuery {
|
|||||||
attributes_to_search_on,
|
attributes_to_search_on,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
personalization,
|
personalize,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let mut debug = f.debug_struct("SearchQuery");
|
let mut debug = f.debug_struct("SearchQuery");
|
||||||
@ -342,8 +340,8 @@ impl fmt::Debug for SearchQuery {
|
|||||||
debug.field("locales", &locales);
|
debug.field("locales", &locales);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(personalization) = personalization {
|
if let Some(personalize) = personalize {
|
||||||
debug.field("personalization", &personalization);
|
debug.field("personalize", &personalize);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.finish()
|
debug.finish()
|
||||||
@ -548,9 +546,9 @@ pub struct SearchQueryWithIndex {
|
|||||||
pub ranking_score_threshold: Option<RankingScoreThreshold>,
|
pub ranking_score_threshold: Option<RankingScoreThreshold>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchLocales>, default)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchLocales>, default)]
|
||||||
pub locales: Option<Vec<Locale>>,
|
pub locales: Option<Vec<Locale>>,
|
||||||
#[deserr(default, error = DeserrJsonError<InvalidSearchPersonalization>, default)]
|
#[deserr(default, error = DeserrJsonError<InvalidSearchPersonalize>, default)]
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub personalization: Option<Personalization>,
|
pub personalize: Option<Personalize>,
|
||||||
|
|
||||||
#[deserr(default)]
|
#[deserr(default)]
|
||||||
pub federation_options: Option<FederationOptions>,
|
pub federation_options: Option<FederationOptions>,
|
||||||
@ -607,7 +605,7 @@ impl SearchQueryWithIndex {
|
|||||||
attributes_to_search_on,
|
attributes_to_search_on,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
personalization,
|
personalize,
|
||||||
} = query;
|
} = query;
|
||||||
|
|
||||||
SearchQueryWithIndex {
|
SearchQueryWithIndex {
|
||||||
@ -638,7 +636,7 @@ impl SearchQueryWithIndex {
|
|||||||
attributes_to_search_on,
|
attributes_to_search_on,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
personalization,
|
personalize,
|
||||||
federation_options,
|
federation_options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -673,7 +671,7 @@ impl SearchQueryWithIndex {
|
|||||||
hybrid,
|
hybrid,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
personalization,
|
personalize,
|
||||||
} = self;
|
} = self;
|
||||||
(
|
(
|
||||||
index_uid,
|
index_uid,
|
||||||
@ -704,7 +702,7 @@ impl SearchQueryWithIndex {
|
|||||||
hybrid,
|
hybrid,
|
||||||
ranking_score_threshold,
|
ranking_score_threshold,
|
||||||
locales,
|
locales,
|
||||||
personalization,
|
personalize,
|
||||||
// do not use ..Default::default() here,
|
// do not use ..Default::default() here,
|
||||||
// rather add any missing field from `SearchQuery` to `SearchQueryWithIndex`
|
// rather add any missing field from `SearchQuery` to `SearchQueryWithIndex`
|
||||||
},
|
},
|
||||||
@ -1157,7 +1155,7 @@ pub fn perform_search(
|
|||||||
attributes_to_search_on: _,
|
attributes_to_search_on: _,
|
||||||
filter: _,
|
filter: _,
|
||||||
distinct: _,
|
distinct: _,
|
||||||
personalization: _,
|
personalize: _,
|
||||||
} = query;
|
} = query;
|
||||||
|
|
||||||
let format = AttributesFormat {
|
let format = AttributesFormat {
|
||||||
|
Reference in New Issue
Block a user