761: Integrate deserr r=irevoire a=loiclec

1. `Setting<T>` now implements `DeserializeFromValue`
2. The settings now store ranking rules as strongly typed `Criterion` instead of `String`, since the validation of the ranking rules will be done on meilisearch's side from now on


Co-authored-by: Loïc Lecrenier <loic.lecrenier@me.com>
This commit is contained in:
bors[bot] 2023-01-11 14:35:15 +00:00 committed by GitHub
commit 302d6cccd7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 45 additions and 29 deletions

View file

@ -343,7 +343,7 @@ mod tests {
use maplit::hashset;
use crate::index::tests::TempIndex;
use crate::{AscDesc, Filter, Search, SearchResult};
use crate::{AscDesc, Criterion, Filter, Search, SearchResult};
// Note that in this test, only the iterative sort algorithms are used. Set the CANDIDATES_THESHOLD
// constant to 0 to ensure that the other sort algorithms are also correct.
@ -356,7 +356,7 @@ mod tests {
settings.set_primary_key("id".to_owned());
settings
.set_sortable_fields(maplit::hashset! { S("id"), S("mod_10"), S("mod_20") });
settings.set_criteria(vec!["sort".to_owned()]);
settings.set_criteria(vec![Criterion::Sort]);
})
.unwrap();
@ -443,7 +443,7 @@ mod tests {
settings.set_primary_key("id".to_owned());
settings.set_filterable_fields(hashset! { S("id"), S("mod_10"), S("mod_20") });
settings.set_sortable_fields(hashset! { S("id"), S("mod_10"), S("mod_20") });
settings.set_criteria(vec!["sort".to_owned()]);
settings.set_criteria(vec![Criterion::Sort]);
})
.unwrap();

View file

@ -497,7 +497,7 @@ mod tests {
create_disjoint_combinations, create_non_disjoint_combinations,
};
use crate::snapshot_tests::display_bitmap;
use crate::SearchResult;
use crate::{Criterion, SearchResult};
#[test]
fn test_exact_words_subcriterion() {
@ -506,7 +506,7 @@ mod tests {
index
.update_settings(|settings| {
settings.set_primary_key(S("id"));
settings.set_criteria(vec!["exactness".to_owned()]);
settings.set_criteria(vec![Criterion::Exactness]);
})
.unwrap();

View file

@ -599,7 +599,7 @@ mod tests {
use crate::documents::{DocumentsBatchBuilder, DocumentsBatchReader};
use crate::index::tests::TempIndex;
use crate::{CriterionImplementationStrategy, SearchResult};
use crate::{Criterion, CriterionImplementationStrategy, SearchResult};
fn documents_with_enough_different_words_for_prefixes(prefixes: &[&str]) -> Vec<crate::Object> {
let mut documents = Vec::new();
@ -627,9 +627,9 @@ mod tests {
.update_settings(|settings| {
settings.set_primary_key(S("id"));
settings.set_criteria(vec![
"words".to_owned(),
"typo".to_owned(),
"proximity".to_owned(),
Criterion::Words,
Criterion::Typo,
Criterion::Proximity,
]);
})
.unwrap();

View file

@ -2,6 +2,7 @@ use std::collections::{BTreeSet, HashMap, HashSet};
use std::result::Result as StdResult;
use charabia::{Tokenizer, TokenizerBuilder};
use deserr::{DeserializeError, DeserializeFromValue};
use itertools::Itertools;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use time::OffsetDateTime;
@ -22,6 +23,25 @@ pub enum Setting<T> {
NotSet,
}
impl<T, E> DeserializeFromValue<E> for Setting<T>
where
T: DeserializeFromValue<E>,
E: DeserializeError,
{
fn deserialize_from_value<V: deserr::IntoValue>(
value: deserr::Value<V>,
location: deserr::ValuePointerRef,
) -> std::result::Result<Self, E> {
match value {
deserr::Value::Null => Ok(Setting::Reset),
_ => T::deserialize_from_value(value, location).map(Setting::Set),
}
}
fn default() -> Option<Self> {
Some(Self::NotSet)
}
}
impl<T> Default for Setting<T> {
fn default() -> Self {
Self::NotSet
@ -93,7 +113,7 @@ pub struct Settings<'a, 't, 'u, 'i> {
displayed_fields: Setting<Vec<String>>,
filterable_fields: Setting<HashSet<String>>,
sortable_fields: Setting<HashSet<String>>,
criteria: Setting<Vec<String>>,
criteria: Setting<Vec<Criterion>>,
stop_words: Setting<BTreeSet<String>>,
distinct_field: Setting<String>,
synonyms: Setting<HashMap<String, Vec<String>>>,
@ -173,7 +193,7 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
self.criteria = Setting::Reset;
}
pub fn set_criteria(&mut self, criteria: Vec<String>) {
pub fn set_criteria(&mut self, criteria: Vec<Criterion>) {
self.criteria = Setting::Set(criteria);
}
@ -526,14 +546,9 @@ impl<'a, 't, 'u, 'i> Settings<'a, 't, 'u, 'i> {
}
fn update_criteria(&mut self) -> Result<()> {
match self.criteria {
Setting::Set(ref fields) => {
let mut new_criteria = Vec::new();
for name in fields {
let criterion: Criterion = name.parse()?;
new_criteria.push(criterion);
}
self.index.put_criteria(self.wtxn, &new_criteria)?;
match &self.criteria {
Setting::Set(criteria) => {
self.index.put_criteria(self.wtxn, criteria)?;
}
Setting::Reset => {
self.index.delete_criteria(self.wtxn)?;
@ -977,7 +992,7 @@ mod tests {
index
.update_settings(|settings| {
settings.set_displayed_fields(vec![S("name")]);
settings.set_criteria(vec![S("age:asc")]);
settings.set_criteria(vec![Criterion::Asc("age".to_owned())]);
})
.unwrap();
@ -1246,7 +1261,7 @@ mod tests {
.update_settings(|settings| {
settings.set_displayed_fields(vec!["hello".to_string()]);
settings.set_filterable_fields(hashset! { S("age"), S("toto") });
settings.set_criteria(vec!["toto:asc".to_string()]);
settings.set_criteria(vec![Criterion::Asc(S("toto"))]);
})
.unwrap();
@ -1280,7 +1295,7 @@ mod tests {
.update_settings(|settings| {
settings.set_displayed_fields(vec!["hello".to_string()]);
// It is only Asc(toto), there is a facet database but it is denied to filter with toto.
settings.set_criteria(vec!["toto:asc".to_string()]);
settings.set_criteria(vec![Criterion::Asc(S("toto"))]);
})
.unwrap();