diff --git a/meilisearch-core/src/query_builder.rs b/meilisearch-core/src/query_builder.rs index 5a995030e..c323b8c1f 100644 --- a/meilisearch-core/src/query_builder.rs +++ b/meilisearch-core/src/query_builder.rs @@ -12,9 +12,9 @@ use crate::facets::FacetFilter; use either::Either; use sdset::SetOperation; -use meilisearch_schema::{Schema, FieldId}; +use meilisearch_schema::FieldId; -pub struct QueryBuilder<'c, 'f, 'd, 'i, 'q> { +pub struct QueryBuilder<'c, 'f, 'd, 'i> { criteria: Criteria<'c>, searchable_attrs: Option, filter: Option bool + 'f>>, @@ -25,7 +25,7 @@ pub struct QueryBuilder<'c, 'f, 'd, 'i, 'q> { facets: Option>, } -impl<'c, 'f, 'd, 'i, 'q> QueryBuilder<'c, 'f, 'd, 'i, 'q> { +impl<'c, 'f, 'd, 'i> QueryBuilder<'c, 'f, 'd, 'i> { pub fn new(index: &'i store::Index) -> Self { QueryBuilder::with_criteria( index, @@ -39,7 +39,7 @@ impl<'c, 'f, 'd, 'i, 'q> QueryBuilder<'c, 'f, 'd, 'i, 'q> { } /// sets facet attributes for which to return the count - pub fn set_facets(&mut self, facets: Option<&'q [FieldId]>) { + pub fn set_facets(&mut self, facets: Option>) { self.facets = facets; } @@ -87,7 +87,6 @@ impl<'c, 'f, 'd, 'i, 'q> QueryBuilder<'c, 'f, 'd, 'i, 'q> { reader: &heed::RoTxn, query: &str, range: Range, - schema: &Schema, ) -> MResult { let facets_docids = match self.facet_filter { Some(facets) => { @@ -127,16 +126,14 @@ impl<'c, 'f, 'd, 'i, 'q> QueryBuilder<'c, 'f, 'd, 'i, 'q> { let facet_count_docids = match self.facets { Some(field_ids) => { let mut facet_count_map = HashMap::new(); - for field_id in field_ids { - if let Some(field_name) = schema.name(*field_id) { - let mut key_map = HashMap::new(); - for pair in self.index.facets.field_document_ids(reader, *field_id)? { - let (facet_key, document_ids) = pair?; - let value = facet_key.value(); - key_map.insert(value.to_string(), document_ids); - } - facet_count_map.insert(field_name.to_string(), key_map); + for (field_id, field_name) in field_ids { + let mut key_map = HashMap::new(); + for pair in self.index.facets.field_document_ids(reader, field_id)? { + let (facet_key, document_ids) = pair?; + let value = facet_key.value(); + key_map.insert(value.to_string(), document_ids); } + facet_count_map.insert(field_name, key_map); } Some(facet_count_map) } diff --git a/meilisearch-core/src/store/mod.rs b/meilisearch-core/src/store/mod.rs index fb3d68849..6448a3441 100644 --- a/meilisearch-core/src/store/mod.rs +++ b/meilisearch-core/src/store/mod.rs @@ -366,7 +366,7 @@ impl Index { pub fn query_builder_with_criteria<'c, 'f, 'd, 'i>( &'i self, criteria: Criteria<'c>, - ) -> QueryBuilder<'c, 'f, 'd, 'i, 'q> { + ) -> QueryBuilder<'c, 'f, 'd, 'i> { QueryBuilder::with_criteria(self, criteria) } } diff --git a/meilisearch-http/src/helpers/meilisearch.rs b/meilisearch-http/src/helpers/meilisearch.rs index 66ff58b61..e50fbcaad 100644 --- a/meilisearch-http/src/helpers/meilisearch.rs +++ b/meilisearch-http/src/helpers/meilisearch.rs @@ -52,7 +52,7 @@ pub struct SearchBuilder<'a> { filters: Option, matches: bool, facet_filters: Option, - facets: Option> + facets: Option> } impl<'a> SearchBuilder<'a> { @@ -102,12 +102,12 @@ impl<'a> SearchBuilder<'a> { self } - pub fn add_facets(&mut self, facets: Vec) -> &SearchBuilder { + pub fn add_facets(&mut self, facets: Vec<(FieldId, String)>) -> &SearchBuilder { self.facets = Some(facets); self } - pub fn search(&self, reader: &heed::RoTxn) -> Result { + pub fn search(self, reader: &heed::RoTxn) -> Result { let schema = self .index .main @@ -124,8 +124,8 @@ impl<'a> SearchBuilder<'a> { if let Some(filter_expression) = &self.filters { let filter = Filter::parse(filter_expression, &schema)?; + let index = &self.index; query_builder.with_filter(move |id| { - let index = &self.index; let reader = &reader; let filter = &filter; match filter.test(reader, index, id) { @@ -140,8 +140,9 @@ impl<'a> SearchBuilder<'a> { if let Some(field) = self.index.main.distinct_attribute(reader)? { if let Some(field_id) = schema.id(&field) { + let index = &self.index; query_builder.with_distinct(1, move |id| { - match self.index.document_attribute_bytes(reader, id, field_id) { + match index.document_attribute_bytes(reader, id, field_id) { Ok(Some(bytes)) => { let mut s = SipHasher::new(); bytes.hash(&mut s); @@ -153,11 +154,11 @@ impl<'a> SearchBuilder<'a> { } } - query_builder.set_facet_filters(self.facet_filters.as_ref()); - query_builder.set_facets(self.facets.as_deref()); + query_builder.set_facet_filters(self.facet_filters); + query_builder.set_facets(self.facets); let start = Instant::now(); - let result = query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit), &schema); + let result = query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit)); let search_result = result.map_err(ResponseError::search_documents)?; let time_ms = start.elapsed().as_millis() as usize; diff --git a/meilisearch-http/src/routes/search.rs b/meilisearch-http/src/routes/search.rs index 731a6ec90..5d086d128 100644 --- a/meilisearch-http/src/routes/search.rs +++ b/meilisearch-http/src/routes/search.rs @@ -176,9 +176,13 @@ fn prepare_facet_list(facets: &str, schema: &Schema, facet_attrs: &[FieldId]) -> Value::Array(vals) => { let wildcard = Value::String("*".to_string()); if vals.iter().any(|f| f == &wildcard) { - return Ok(Vec::from(facet_attrs)); + let attrs = facet_attrs + .iter() + .filter_map(|&id| schema.name(id).map(|n| (id, n.to_string()))) + .collect(); + return Ok(attrs); } - let mut field_ids = Vec::new(); + let mut field_ids = Vec::with_capacity(facet_attrs.len()); for facet in vals { match facet { Value::String(facet) => { @@ -186,7 +190,7 @@ fn prepare_facet_list(facets: &str, schema: &Schema, facet_attrs: &[FieldId]) -> if !facet_attrs.contains(&id) { return Err(ResponseError::FacetExpression("Only attributes set as facet can be counted".to_string())); // TODO make special error } - field_ids.push(id); + field_ids.push((id, facet)); } } bad_val => return Err(ResponseError::FacetExpression(format!("expected String found {}", bad_val)))