Implement localized attributes settings

This commit is contained in:
ManyTheFish 2024-07-23 14:51:36 +02:00 committed by Louis Dureuil
parent 90c0a6db7d
commit 04fa44e7eb
No known key found for this signature in database
18 changed files with 405 additions and 209 deletions

View file

@ -6,6 +6,7 @@ use meilisearch_types::deserr::DeserrJsonError;
use meilisearch_types::error::deserr_codes::*;
use meilisearch_types::error::ResponseError;
use meilisearch_types::index_uid::IndexUid;
use meilisearch_types::locales::Locale;
use serde_json::Value;
use tracing::debug;
@ -48,6 +49,8 @@ pub struct FacetSearchQuery {
pub attributes_to_search_on: Option<Vec<String>>,
#[deserr(default, error = DeserrJsonError<InvalidSearchRankingScoreThreshold>, default)]
pub ranking_score_threshold: Option<RankingScoreThreshold>,
#[deserr(default, error = DeserrJsonError<InvalidSearchLocales>, default)]
pub locales: Option<Vec<Locale>>,
}
pub async fn search(
@ -67,6 +70,7 @@ pub async fn search(
let facet_query = query.facet_query.clone();
let facet_name = query.facet_name.clone();
let locales = query.locales.clone().map(|l| l.into_iter().map(Into::into).collect());
let mut search_query = SearchQuery::from(query);
// Tenant token search_rules.
@ -86,6 +90,7 @@ pub async fn search(
facet_name,
search_kind,
index_scheduler.features(),
locales
)
})
.await?;
@ -113,6 +118,7 @@ impl From<FacetSearchQuery> for SearchQuery {
attributes_to_search_on,
hybrid,
ranking_score_threshold,
locales,
} = value;
SearchQuery {
@ -141,6 +147,7 @@ impl From<FacetSearchQuery> for SearchQuery {
attributes_to_search_on,
hybrid,
ranking_score_threshold,
locales,
}
}
}

View file

@ -474,6 +474,28 @@ make_setting_route!(
}
);
make_setting_route!(
"/localized-attributes",
put,
Vec<meilisearch_types::locales::LocalizedAttributesRuleView>,
meilisearch_types::deserr::DeserrJsonError<
meilisearch_types::error::deserr_codes::InvalidSettingsLocalizedAttributes,
>,
localized_attributes,
"localizedAttributes",
analytics,
|rules: &Option<Vec<meilisearch_types::locales::LocalizedAttributesRuleView>>, req: &HttpRequest| {
use serde_json::json;
analytics.publish(
"LocalizedAttributesRules Updated".to_string(),
json!({
"locales": rules.as_ref().map(|rules| rules.iter().map(|rule| rule.locales.iter().cloned()).flatten().collect::<std::collections::BTreeSet<_>>())
}),
Some(req),
);
}
);
make_setting_route!(
"/ranking-rules",
put,
@ -786,6 +808,7 @@ pub async fn update_all(
},
"embedders": crate::routes::indexes::settings::embedder_analytics(new_settings.embedders.as_ref().set()),
"search_cutoff_ms": new_settings.search_cutoff_ms.as_ref().set(),
"locales": new_settings.localized_attributes.as_ref().set().map(|rules| rules.into_iter().map(|rule| rule.locales.iter().cloned()).flatten().collect::<std::collections::BTreeSet<_>>()),
}),
Some(&req),
);

View file

@ -1290,6 +1290,9 @@ impl<'a> HitMaker<'a> {
document.insert("_vectors".into(), vectors.into());
}
let localized_attributes =
self.index.localized_attributes_rules(self.rtxn)?.unwrap_or_default();
let (matches_position, formatted) = format_fields(
&displayed_document,
&self.fields_ids_map,
@ -1298,6 +1301,7 @@ impl<'a> HitMaker<'a> {
self.show_matches_position,
&self.displayed_ids,
self.locales.as_deref(),
&localized_attributes,
)?;
if let Some(sort) = self.sort.as_ref() {
@ -1365,6 +1369,14 @@ pub fn perform_facet_search(
None => TimeBudget::default(),
};
let localized_attributes = index.localized_attributes_rules(&rtxn)?.unwrap_or_default();
let locales = locales.or_else(|| {
localized_attributes
.into_iter()
.find(|attr| attr.match_str(&facet_name))
.map(|attr| attr.locales)
});
let (search, _, _, _) =
prepare_search(index, &rtxn, &search_query, &search_kind, time_budget, features)?;
let mut facet_search = SearchForFacetValues::new(
@ -1653,6 +1665,7 @@ fn format_fields(
compute_matches: bool,
displayable_ids: &BTreeSet<FieldId>,
locales: Option<&[Language]>,
localized_attributes: &[LocalizedAttributesRule],
) -> Result<(Option<MatchesPosition>, Document), MeilisearchHttpError> {
let mut matches_position = compute_matches.then(BTreeMap::new);
let mut document = document.clone();
@ -1685,7 +1698,14 @@ fn format_fields(
.reduce(|acc, option| acc.merge(option));
let mut infos = Vec::new();
*value = format_value(std::mem::take(value), builder, format, &mut infos, compute_matches);
// if no locales has been provided, we try to find the locales in the localized_attributes.
let locales = locales.or_else(|| {
localized_attributes
.iter()
.find(|rule| rule.match_str(key))
.map(LocalizedAttributesRule::locales)
});
*value = format_value(
std::mem::take(value),
builder,