Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.

Commit 660d8bb

Browse files
bors[bot]curquiza
andauthored
Merge #318
318: Revert "Sort at query time" r=Kerollmops a=curquiza Reverts #309 We revert this from `main` not because this leads to a bug, but because we don't want to release it now and we have to merge and release an hotfix on `main`. Cf: - #316 - #317 Once the v0.21.0 is released, we should merge again this awesome addition 👌 Co-authored-by: Clémentine Urquizar <clementine@meilisearch.com>
2 parents 41fc0dc + 922f9fd commit 660d8bb

File tree

17 files changed

+148
-701
lines changed

17 files changed

+148
-701
lines changed

benchmarks/benches/search_songs.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ fn bench_songs(c: &mut criterion::Criterion) {
5252
milli::default_criteria().iter().map(|criteria| criteria.to_string()).collect();
5353
let default_criterion = default_criterion.iter().map(|s| s.as_str());
5454
let asc_default: Vec<&str> =
55-
std::iter::once("released-timestamp:asc").chain(default_criterion.clone()).collect();
55+
std::iter::once("asc(released-timestamp)").chain(default_criterion.clone()).collect();
5656
let desc_default: Vec<&str> =
57-
std::iter::once("released-timestamp:desc").chain(default_criterion.clone()).collect();
57+
std::iter::once("desc(released-timestamp)").chain(default_criterion.clone()).collect();
5858

5959
let basic_with_quote: Vec<String> = BASE_CONF
6060
.queries
@@ -118,12 +118,12 @@ fn bench_songs(c: &mut criterion::Criterion) {
118118
},
119119
utils::Conf {
120120
group_name: "asc",
121-
criterion: Some(&["released-timestamp:desc"]),
121+
criterion: Some(&["asc(released-timestamp)"]),
122122
..BASE_CONF
123123
},
124124
utils::Conf {
125125
group_name: "desc",
126-
criterion: Some(&["released-timestamp:desc"]),
126+
criterion: Some(&["desc(released-timestamp)"]),
127127
..BASE_CONF
128128
},
129129

http-ui/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,7 @@ mod tests {
10301030
displayed_attributes: Setting::Set(vec!["name".to_string()]),
10311031
searchable_attributes: Setting::Set(vec!["age".to_string()]),
10321032
filterable_attributes: Setting::Set(hashset! { "age".to_string() }),
1033-
criteria: Setting::Set(vec!["age:asc".to_string()]),
1033+
criteria: Setting::Set(vec!["asc(age)".to_string()]),
10341034
stop_words: Setting::Set(btreeset! { "and".to_string() }),
10351035
synonyms: Setting::Set(hashmap! { "alex".to_string() => vec!["alexey".to_string()] }),
10361036
};
@@ -1058,7 +1058,7 @@ mod tests {
10581058
Token::Str("criteria"),
10591059
Token::Some,
10601060
Token::Seq { len: Some(1) },
1061-
Token::Str("age:asc"),
1061+
Token::Str("asc(age)"),
10621062
Token::SeqEnd,
10631063
Token::Str("stopWords"),
10641064
Token::Some,

milli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ obkv = "0.2.0"
2525
once_cell = "1.5.2"
2626
ordered-float = "2.1.1"
2727
rayon = "1.5.0"
28+
regex = "1.4.3"
2829
roaring = "0.6.6"
2930
serde = { version = "1.0.123", features = ["derive"] }
3031
serde_json = { version = "1.0.62", features = ["preserve_order"] }

milli/src/criterion.rs

Lines changed: 26 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
use std::fmt;
22
use std::str::FromStr;
33

4+
use once_cell::sync::Lazy;
5+
use regex::Regex;
46
use serde::{Deserialize, Serialize};
57

68
use crate::error::{Error, UserError};
79

10+
static ASC_DESC_REGEX: Lazy<Regex> =
11+
Lazy::new(|| Regex::new(r#"(asc|desc)\(([\w_-]+)\)"#).unwrap());
12+
813
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
914
pub enum Criterion {
1015
/// Sorted by decreasing number of matched query terms.
1116
/// Query words at the front of an attribute is considered better than if it was at the back.
1217
Words,
1318
/// Sorted by increasing number of typos.
1419
Typo,
15-
/// Dynamically sort at query time the documents. None, one or multiple Asc/Desc sortable
16-
/// attributes can be used in place of this criterion at query time.
17-
Sort,
1820
/// Sorted by increasing distance between matched query terms.
1921
Proximity,
2022
/// Documents with quey words contained in more important
21-
/// attributes are considered better.
23+
/// attributes are considred better.
2224
Attribute,
2325
/// Sorted by the similarity of the matched words with the query words.
2426
Exactness,
@@ -41,46 +43,29 @@ impl Criterion {
4143
impl FromStr for Criterion {
4244
type Err = Error;
4345

44-
fn from_str(text: &str) -> Result<Criterion, Self::Err> {
45-
match text {
46+
fn from_str(txt: &str) -> Result<Criterion, Self::Err> {
47+
match txt {
4648
"words" => Ok(Criterion::Words),
4749
"typo" => Ok(Criterion::Typo),
48-
"sort" => Ok(Criterion::Sort),
4950
"proximity" => Ok(Criterion::Proximity),
5051
"attribute" => Ok(Criterion::Attribute),
5152
"exactness" => Ok(Criterion::Exactness),
52-
text => match AscDesc::from_str(text) {
53-
Ok(AscDesc::Asc(field)) => Ok(Criterion::Asc(field)),
54-
Ok(AscDesc::Desc(field)) => Ok(Criterion::Desc(field)),
55-
Err(error) => Err(error.into()),
56-
},
57-
}
58-
}
59-
}
60-
61-
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
62-
pub enum AscDesc {
63-
Asc(String),
64-
Desc(String),
65-
}
66-
67-
impl AscDesc {
68-
pub fn field(&self) -> &str {
69-
match self {
70-
AscDesc::Asc(field) => field,
71-
AscDesc::Desc(field) => field,
72-
}
73-
}
74-
}
75-
76-
impl FromStr for AscDesc {
77-
type Err = UserError;
78-
79-
fn from_str(text: &str) -> Result<AscDesc, Self::Err> {
80-
match text.rsplit_once(':') {
81-
Some((field_name, "asc")) => Ok(AscDesc::Asc(field_name.to_string())),
82-
Some((field_name, "desc")) => Ok(AscDesc::Desc(field_name.to_string())),
83-
_ => Err(UserError::InvalidCriterionName { name: text.to_string() }),
53+
text => {
54+
let caps = ASC_DESC_REGEX
55+
.captures(text)
56+
.ok_or_else(|| UserError::InvalidCriterionName { name: text.to_string() })?;
57+
let order = caps.get(1).unwrap().as_str();
58+
let field_name = caps.get(2).unwrap().as_str();
59+
match order {
60+
"asc" => Ok(Criterion::Asc(field_name.to_string())),
61+
"desc" => Ok(Criterion::Desc(field_name.to_string())),
62+
text => {
63+
return Err(
64+
UserError::InvalidCriterionName { name: text.to_string() }.into()
65+
)
66+
}
67+
}
68+
}
8469
}
8570
}
8671
}
@@ -89,7 +74,6 @@ pub fn default_criteria() -> Vec<Criterion> {
8974
vec![
9075
Criterion::Words,
9176
Criterion::Typo,
92-
Criterion::Sort,
9377
Criterion::Proximity,
9478
Criterion::Attribute,
9579
Criterion::Exactness,
@@ -103,12 +87,11 @@ impl fmt::Display for Criterion {
10387
match self {
10488
Words => f.write_str("words"),
10589
Typo => f.write_str("typo"),
106-
Sort => f.write_str("sort"),
10790
Proximity => f.write_str("proximity"),
10891
Attribute => f.write_str("attribute"),
10992
Exactness => f.write_str("exactness"),
110-
Asc(attr) => write!(f, "{}:asc", attr),
111-
Desc(attr) => write!(f, "{}:desc", attr),
93+
Asc(attr) => write!(f, "asc({})", attr),
94+
Desc(attr) => write!(f, "desc({})", attr),
11295
}
11396
}
11497
}

milli/src/error.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ pub enum UserError {
5858
InvalidFacetsDistribution { invalid_facets_name: HashSet<String> },
5959
InvalidFilter(pest::error::Error<ParserRule>),
6060
InvalidFilterAttribute(pest::error::Error<ParserRule>),
61-
InvalidSortableAttribute { field: String, valid_fields: HashSet<String> },
6261
InvalidStoreFile,
6362
MaxDatabaseSizeReached,
6463
MissingDocumentId { document: Object },
@@ -227,15 +226,6 @@ only composed of alphanumeric characters (a-z A-Z 0-9), hyphens (-) and undersco
227226
)
228227
}
229228
Self::InvalidFilterAttribute(error) => error.fmt(f),
230-
Self::InvalidSortableAttribute { field, valid_fields } => {
231-
let valid_names =
232-
valid_fields.iter().map(AsRef::as_ref).collect::<Vec<_>>().join(", ");
233-
write!(
234-
f,
235-
"Attribute {} is not sortable, available sortable attributes are: {}",
236-
field, valid_names
237-
)
238-
}
239229
Self::MissingDocumentId { document } => {
240230
let json = serde_json::to_string(document).unwrap();
241231
write!(f, "document doesn't have an identifier {}", json)

milli/src/index.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ pub mod main_key {
2828
pub const DISTINCT_FIELD_KEY: &str = "distinct-field-key";
2929
pub const DOCUMENTS_IDS_KEY: &str = "documents-ids";
3030
pub const FILTERABLE_FIELDS_KEY: &str = "filterable-fields";
31-
pub const SORTABLE_FIELDS_KEY: &str = "sortable-fields";
3231
pub const FIELD_DISTRIBUTION_KEY: &str = "fields-distribution";
3332
pub const FIELDS_IDS_MAP_KEY: &str = "fields-ids-map";
3433
pub const HARD_EXTERNAL_DOCUMENTS_IDS_KEY: &str = "hard-external-documents-ids";
@@ -447,45 +446,13 @@ impl Index {
447446
Ok(fields_ids)
448447
}
449448

450-
/* sortable fields */
451-
452-
/// Writes the sortable fields names in the database.
453-
pub(crate) fn put_sortable_fields(
454-
&self,
455-
wtxn: &mut RwTxn,
456-
fields: &HashSet<String>,
457-
) -> heed::Result<()> {
458-
self.main.put::<_, Str, SerdeJson<_>>(wtxn, main_key::SORTABLE_FIELDS_KEY, fields)
459-
}
460-
461-
/// Deletes the sortable fields ids in the database.
462-
pub(crate) fn delete_sortable_fields(&self, wtxn: &mut RwTxn) -> heed::Result<bool> {
463-
self.main.delete::<_, Str>(wtxn, main_key::SORTABLE_FIELDS_KEY)
464-
}
465-
466-
/// Returns the sortable fields names.
467-
pub fn sortable_fields(&self, rtxn: &RoTxn) -> heed::Result<HashSet<String>> {
468-
Ok(self
469-
.main
470-
.get::<_, Str, SerdeJson<_>>(rtxn, main_key::SORTABLE_FIELDS_KEY)?
471-
.unwrap_or_default())
472-
}
473-
474-
/// Identical to `sortable_fields`, but returns ids instead.
475-
pub fn sortable_fields_ids(&self, rtxn: &RoTxn) -> Result<HashSet<FieldId>> {
476-
let fields = self.sortable_fields(rtxn)?;
477-
let fields_ids_map = self.fields_ids_map(rtxn)?;
478-
Ok(fields.into_iter().filter_map(|name| fields_ids_map.id(&name)).collect())
479-
}
480-
481449
/* faceted documents ids */
482450

483451
/// Returns the faceted fields names.
484452
///
485-
/// Faceted fields are the union of all the filterable, sortable, distinct, and Asc/Desc fields.
453+
/// Faceted fields are the union of all the filterable, distinct, and Asc/Desc fields.
486454
pub fn faceted_fields(&self, rtxn: &RoTxn) -> Result<HashSet<String>> {
487455
let filterable_fields = self.filterable_fields(rtxn)?;
488-
let sortable_fields = self.sortable_fields(rtxn)?;
489456
let distinct_field = self.distinct_field(rtxn)?;
490457
let asc_desc_fields =
491458
self.criteria(rtxn)?.into_iter().filter_map(|criterion| match criterion {
@@ -494,7 +461,6 @@ impl Index {
494461
});
495462

496463
let mut faceted_fields = filterable_fields;
497-
faceted_fields.extend(sortable_fields);
498464
faceted_fields.extend(asc_desc_fields);
499465
if let Some(field) = distinct_field {
500466
faceted_fields.insert(field.to_owned());

milli/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::result::Result as StdResult;
2222
use fxhash::{FxHasher32, FxHasher64};
2323
use serde_json::{Map, Value};
2424

25-
pub use self::criterion::{default_criteria, AscDesc, Criterion};
25+
pub use self::criterion::{default_criteria, Criterion};
2626
pub use self::error::{
2727
Error, FieldIdMapMissingEntry, InternalError, SerializationError, UserError,
2828
};

0 commit comments

Comments
 (0)