diff --git a/milli/src/search/mod.rs b/milli/src/search/mod.rs index 0792ce799..734671990 100644 --- a/milli/src/search/mod.rs +++ b/milli/src/search/mod.rs @@ -113,6 +113,7 @@ impl<'a> Search<'a> { &self.query, self.terms_matching_strategy, &self.filter, + &self.sort_criteria, self.offset, self.limit, Some(self.words_limit), diff --git a/milli/src/search/new/mod.rs b/milli/src/search/new/mod.rs index 66feeab99..5a282891b 100644 --- a/milli/src/search/new/mod.rs +++ b/milli/src/search/new/mod.rs @@ -33,7 +33,11 @@ use roaring::RoaringBitmap; use words::Words; use self::ranking_rules::{BoxRankingRule, RankingRule}; -use crate::{Filter, Index, MatchingWords, Result, SearchResult, TermsMatchingStrategy}; +use self::sort::Sort; +use crate::{ + AscDesc, CriterionError, Filter, Index, MatchingWords, Member, Result, SearchResult, + TermsMatchingStrategy, +}; /// A structure used throughout the execution of a search query. pub struct SearchContext<'ctx> { @@ -106,6 +110,7 @@ fn resolve_maximally_reduced_query_graph( /// Return the list of initialised ranking rules to be used for a placeholder search. fn get_ranking_rules_for_placeholder_search<'ctx>( ctx: &SearchContext<'ctx>, + sort_criteria: &Option>, ) -> Result>> { // let sort = false; // let mut asc = HashSet::new(); @@ -131,13 +136,14 @@ fn get_ranking_rules_for_placeholder_search<'ctx>( /// Return the list of initialised ranking rules to be used for a query graph search. fn get_ranking_rules_for_query_graph_search<'ctx>( ctx: &SearchContext<'ctx>, + sort_criteria: &Option>, terms_matching_strategy: TermsMatchingStrategy, ) -> Result>> { // query graph search let mut words = false; let mut typo = false; let mut proximity = false; - let sort = false; + let mut sort = false; let attribute = false; let exactness = false; let mut asc = HashSet::new(); @@ -193,8 +199,33 @@ fn get_ranking_rules_for_query_graph_search<'ctx>( if sort { continue; } - // todo!(); - // sort = false; + + for criterion in sort_criteria.clone().unwrap_or_default() { + let sort_ranking_rule = match criterion { + AscDesc::Asc(Member::Field(field_name)) => { + if asc.contains(&field_name) { + continue; + } + asc.insert(field_name.clone()); + Sort::new(ctx.index, ctx.txn, field_name, true)? + } + AscDesc::Desc(Member::Field(field_name)) => { + if desc.contains(&field_name) { + continue; + } + desc.insert(field_name.clone()); + Sort::new(ctx.index, ctx.txn, field_name, false)? + } + _ => { + return Err(CriterionError::ReservedNameForSort { + name: "_geoPoint".to_string(), + } + .into()) + } + }; + ranking_rules.push(Box::new(sort_ranking_rule)); + } + sort = true; } crate::Criterion::Exactness => { if exactness { @@ -228,6 +259,7 @@ pub fn execute_search( query: &Option, terms_matching_strategy: TermsMatchingStrategy, filters: &Option, + sort_criteria: &Option>, from: usize, length: usize, words_limit: Option, @@ -268,11 +300,12 @@ pub fn execute_search( query_graph_logger, )?; - let ranking_rules = get_ranking_rules_for_query_graph_search(ctx, terms_matching_strategy)?; + let ranking_rules = + get_ranking_rules_for_query_graph_search(ctx, sort_criteria, terms_matching_strategy)?; bucket_sort(ctx, ranking_rules, &graph, &universe, from, length, query_graph_logger)? } else { - let ranking_rules = get_ranking_rules_for_placeholder_search(ctx)?; + let ranking_rules = get_ranking_rules_for_placeholder_search(ctx, sort_criteria)?; bucket_sort( ctx, ranking_rules, diff --git a/milli/src/search/new/sort.rs b/milli/src/search/new/sort.rs index 04152f0f0..53144d00d 100644 --- a/milli/src/search/new/sort.rs +++ b/milli/src/search/new/sort.rs @@ -51,7 +51,7 @@ pub struct Sort<'ctx, Query> { iter: Option>, } impl<'ctx, Query> Sort<'ctx, Query> { - pub fn _new( + pub fn new( index: &Index, rtxn: &'ctx heed::RoTxn, field_name: String,