mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-12-24 21:50:07 +01:00
Introduce the new Sort criterion and AscDesc enum
This commit is contained in:
parent
5b88df508e
commit
687cd2e205
@ -12,6 +12,9 @@ pub enum Criterion {
|
|||||||
Words,
|
Words,
|
||||||
/// Sorted by increasing number of typos.
|
/// Sorted by increasing number of typos.
|
||||||
Typo,
|
Typo,
|
||||||
|
/// Dynamically sort at query time the documents. None, one or multiple Asc/Desc sortable
|
||||||
|
/// attributes can be used in place of this criterion at query time.
|
||||||
|
Sort,
|
||||||
/// Sorted by increasing distance between matched query terms.
|
/// Sorted by increasing distance between matched query terms.
|
||||||
Proximity,
|
Proximity,
|
||||||
/// Documents with quey words contained in more important
|
/// Documents with quey words contained in more important
|
||||||
@ -38,26 +41,46 @@ impl Criterion {
|
|||||||
impl FromStr for Criterion {
|
impl FromStr for Criterion {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(txt: &str) -> Result<Criterion, Self::Err> {
|
fn from_str(text: &str) -> Result<Criterion, Self::Err> {
|
||||||
match txt {
|
match text {
|
||||||
"words" => Ok(Criterion::Words),
|
"words" => Ok(Criterion::Words),
|
||||||
"typo" => Ok(Criterion::Typo),
|
"typo" => Ok(Criterion::Typo),
|
||||||
|
"sort" => Ok(Criterion::Sort),
|
||||||
"proximity" => Ok(Criterion::Proximity),
|
"proximity" => Ok(Criterion::Proximity),
|
||||||
"attribute" => Ok(Criterion::Attribute),
|
"attribute" => Ok(Criterion::Attribute),
|
||||||
"exactness" => Ok(Criterion::Exactness),
|
"exactness" => Ok(Criterion::Exactness),
|
||||||
text => match text.rsplit_once(':') {
|
text => match AscDesc::from_str(text) {
|
||||||
Some((field_name, "asc")) => Ok(Criterion::Asc(field_name.to_string())),
|
Ok(AscDesc::Asc(field)) => Ok(Criterion::Asc(field)),
|
||||||
Some((field_name, "desc")) => Ok(Criterion::Desc(field_name.to_string())),
|
Ok(AscDesc::Desc(field)) => Ok(Criterion::Desc(field)),
|
||||||
_ => Err(UserError::InvalidCriterionName { name: text.to_string() }.into()),
|
Err(error) => Err(error.into()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
|
pub enum AscDesc {
|
||||||
|
Asc(String),
|
||||||
|
Desc(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for AscDesc {
|
||||||
|
type Err = UserError;
|
||||||
|
|
||||||
|
fn from_str(text: &str) -> Result<AscDesc, Self::Err> {
|
||||||
|
match text.rsplit_once(':') {
|
||||||
|
Some((field_name, "asc")) => Ok(AscDesc::Asc(field_name.to_string())),
|
||||||
|
Some((field_name, "desc")) => Ok(AscDesc::Desc(field_name.to_string())),
|
||||||
|
_ => Err(UserError::InvalidCriterionName { name: text.to_string() }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn default_criteria() -> Vec<Criterion> {
|
pub fn default_criteria() -> Vec<Criterion> {
|
||||||
vec![
|
vec![
|
||||||
Criterion::Words,
|
Criterion::Words,
|
||||||
Criterion::Typo,
|
Criterion::Typo,
|
||||||
|
Criterion::Sort,
|
||||||
Criterion::Proximity,
|
Criterion::Proximity,
|
||||||
Criterion::Attribute,
|
Criterion::Attribute,
|
||||||
Criterion::Exactness,
|
Criterion::Exactness,
|
||||||
@ -71,6 +94,7 @@ impl fmt::Display for Criterion {
|
|||||||
match self {
|
match self {
|
||||||
Words => f.write_str("words"),
|
Words => f.write_str("words"),
|
||||||
Typo => f.write_str("typo"),
|
Typo => f.write_str("typo"),
|
||||||
|
Sort => f.write_str("sort"),
|
||||||
Proximity => f.write_str("proximity"),
|
Proximity => f.write_str("proximity"),
|
||||||
Attribute => f.write_str("attribute"),
|
Attribute => f.write_str("attribute"),
|
||||||
Exactness => f.write_str("exactness"),
|
Exactness => f.write_str("exactness"),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use roaring::RoaringBitmap;
|
use roaring::RoaringBitmap;
|
||||||
|
|
||||||
@ -273,8 +274,9 @@ impl<'t> CriteriaBuilder<'t> {
|
|||||||
query_tree: Option<Operation>,
|
query_tree: Option<Operation>,
|
||||||
primitive_query: Option<Vec<PrimitiveQueryPart>>,
|
primitive_query: Option<Vec<PrimitiveQueryPart>>,
|
||||||
filtered_candidates: Option<RoaringBitmap>,
|
filtered_candidates: Option<RoaringBitmap>,
|
||||||
|
sort_criteria: Option<Vec<String>>,
|
||||||
) -> Result<Final<'t>> {
|
) -> Result<Final<'t>> {
|
||||||
use crate::criterion::Criterion as Name;
|
use crate::criterion::{AscDesc as AscDescName, Criterion as Name};
|
||||||
|
|
||||||
let primitive_query = primitive_query.unwrap_or_default();
|
let primitive_query = primitive_query.unwrap_or_default();
|
||||||
|
|
||||||
@ -282,8 +284,30 @@ impl<'t> CriteriaBuilder<'t> {
|
|||||||
Box::new(Initial::new(query_tree, filtered_candidates)) as Box<dyn Criterion>;
|
Box::new(Initial::new(query_tree, filtered_candidates)) as Box<dyn Criterion>;
|
||||||
for name in self.index.criteria(&self.rtxn)? {
|
for name in self.index.criteria(&self.rtxn)? {
|
||||||
criterion = match name {
|
criterion = match name {
|
||||||
Name::Typo => Box::new(Typo::new(self, criterion)),
|
|
||||||
Name::Words => Box::new(Words::new(self, criterion)),
|
Name::Words => Box::new(Words::new(self, criterion)),
|
||||||
|
Name::Typo => Box::new(Typo::new(self, criterion)),
|
||||||
|
Name::Sort => match sort_criteria {
|
||||||
|
Some(ref sort_criteria) => {
|
||||||
|
for text in sort_criteria {
|
||||||
|
criterion = match AscDescName::from_str(text)? {
|
||||||
|
AscDescName::Asc(field) => Box::new(AscDesc::asc(
|
||||||
|
&self.index,
|
||||||
|
&self.rtxn,
|
||||||
|
criterion,
|
||||||
|
field,
|
||||||
|
)?),
|
||||||
|
AscDescName::Desc(field) => Box::new(AscDesc::desc(
|
||||||
|
&self.index,
|
||||||
|
&self.rtxn,
|
||||||
|
criterion,
|
||||||
|
field,
|
||||||
|
)?),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
criterion
|
||||||
|
}
|
||||||
|
None => criterion,
|
||||||
|
},
|
||||||
Name::Proximity => Box::new(Proximity::new(self, criterion)),
|
Name::Proximity => Box::new(Proximity::new(self, criterion)),
|
||||||
Name::Attribute => Box::new(Attribute::new(self, criterion)),
|
Name::Attribute => Box::new(Attribute::new(self, criterion)),
|
||||||
Name::Exactness => Box::new(Exactness::new(self, criterion, &primitive_query)?),
|
Name::Exactness => Box::new(Exactness::new(self, criterion, &primitive_query)?),
|
||||||
|
@ -135,7 +135,13 @@ impl<'a> Search<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let criteria_builder = criteria::CriteriaBuilder::new(self.rtxn, self.index)?;
|
let criteria_builder = criteria::CriteriaBuilder::new(self.rtxn, self.index)?;
|
||||||
let criteria = criteria_builder.build(query_tree, primitive_query, filtered_candidates)?;
|
let sort_criteria = None;
|
||||||
|
let criteria = criteria_builder.build(
|
||||||
|
query_tree,
|
||||||
|
primitive_query,
|
||||||
|
filtered_candidates,
|
||||||
|
sort_criteria,
|
||||||
|
)?;
|
||||||
|
|
||||||
match self.index.distinct_field(self.rtxn)? {
|
match self.index.distinct_field(self.rtxn)? {
|
||||||
None => self.perform_sort(NoopDistinct, matching_words, criteria),
|
None => self.perform_sort(NoopDistinct, matching_words, criteria),
|
||||||
|
@ -90,6 +90,7 @@ pub fn expected_order(
|
|||||||
new_groups
|
new_groups
|
||||||
.extend(group.linear_group_by_key(|d| d.proximity_rank).map(Vec::from));
|
.extend(group.linear_group_by_key(|d| d.proximity_rank).map(Vec::from));
|
||||||
}
|
}
|
||||||
|
Criterion::Sort => todo!("sort not supported right now"),
|
||||||
Criterion::Typo => {
|
Criterion::Typo => {
|
||||||
group.sort_by_key(|d| d.typo_rank);
|
group.sort_by_key(|d| d.typo_rank);
|
||||||
new_groups.extend(group.linear_group_by_key(|d| d.typo_rank).map(Vec::from));
|
new_groups.extend(group.linear_group_by_key(|d| d.typo_rank).map(Vec::from));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user