Apply review suggestions: simplify implementation of exactness criterion

This commit is contained in:
Loïc Lecrenier 2023-01-02 10:46:35 +01:00
parent 32c6062e65
commit b5df889dcb

View File

@ -191,7 +191,7 @@ fn resolve_state(
attribute_start_with_docids(ctx, id, query)?; attribute_start_with_docids(ctx, id, query)?;
attribute_candidates_array.push(attribute_allowed_docids); attribute_candidates_array.push(attribute_allowed_docids);
candidates |= intersection_of(attribute_candidates_array.iter().collect()); candidates |= MultiOps::intersection(attribute_candidates_array);
} }
} }
@ -208,7 +208,7 @@ fn resolve_state(
let attributes_ids = ctx.searchable_fields_ids()?; let attributes_ids = ctx.searchable_fields_ids()?;
for id in attributes_ids { for id in attributes_ids {
let attribute_candidates_array = attribute_start_with_docids(ctx, id, query)?; let attribute_candidates_array = attribute_start_with_docids(ctx, id, query)?;
candidates |= intersection_of(attribute_candidates_array.iter().collect()); candidates |= MultiOps::intersection(attribute_candidates_array);
} }
// only keep allowed candidates // only keep allowed candidates
@ -289,12 +289,6 @@ fn attribute_start_with_docids(
Ok(attribute_candidates_array) Ok(attribute_candidates_array)
} }
#[inline(never)]
fn intersection_of(mut rbs: Vec<&RoaringBitmap>) -> RoaringBitmap {
rbs.sort_unstable_by_key(|rb| rb.len());
roaring::MultiOps::intersection(rbs.into_iter())
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ExactQueryPart { pub enum ExactQueryPart {
Phrase(Vec<Option<String>>), Phrase(Vec<Option<String>>),
@ -440,8 +434,7 @@ fn compute_combinations(
fn create_non_disjoint_combinations(bitmaps: Vec<RoaringBitmap>) -> Vec<RoaringBitmap> { fn create_non_disjoint_combinations(bitmaps: Vec<RoaringBitmap>) -> Vec<RoaringBitmap> {
let nbr_parts = bitmaps.len(); let nbr_parts = bitmaps.len();
if nbr_parts == 1 { if nbr_parts == 1 {
let flattened_base_level = MultiOps::union(bitmaps.into_iter()); return bitmaps;
return vec![flattened_base_level];
} }
let mut flattened_levels = vec![]; let mut flattened_levels = vec![];
let mut last_level: BTreeMap<usize, RoaringBitmap> = let mut last_level: BTreeMap<usize, RoaringBitmap> =
@ -466,12 +459,12 @@ fn create_non_disjoint_combinations(bitmaps: Vec<RoaringBitmap>) -> Vec<RoaringB
} }
} }
// Now flatten the last level to save memory // Now flatten the last level to save memory
let flattened_last_level = MultiOps::union(last_level.values()); let flattened_last_level = MultiOps::union(last_level.into_values());
flattened_levels.push(flattened_last_level); flattened_levels.push(flattened_last_level);
last_level = new_level; last_level = new_level;
} }
// Flatten the last level // Flatten the last level
let flattened_last_level = MultiOps::union(last_level.values()); let flattened_last_level = MultiOps::union(last_level.into_values());
flattened_levels.push(flattened_last_level); flattened_levels.push(flattened_last_level);
flattened_levels flattened_levels
} }
@ -480,27 +473,17 @@ fn create_non_disjoint_combinations(bitmaps: Vec<RoaringBitmap>) -> Vec<RoaringB
/// such that `Xi` contains all the elements that are contained in **exactly** `i+1` bitmaps among `b0,b1,...,bn`. /// such that `Xi` contains all the elements that are contained in **exactly** `i+1` bitmaps among `b0,b1,...,bn`.
/// ///
/// The returned vector is guaranteed to be of length `n`. It is equal to `vec![X0, X1, ..., Xn]`. /// The returned vector is guaranteed to be of length `n`. It is equal to `vec![X0, X1, ..., Xn]`.
///
/// ## Implementation
/// 1. We first create `Y0,Y1,...Yn` such that `Yi` contains all the elements that are contained in
/// **at least** `i+1` bitmaps among `b0,b1,...,bn`. This is done using `create_non_disjoint_combinations`.
///
/// 2. We create a set of "forbidden" elements, `Fn`, which is initialised to the empty set.
///
/// 3. We compute:
/// - `Xn = Yn - Fn`
/// - `Fn-1 = Fn | Xn`
fn create_disjoint_combinations(parts_candidates_array: Vec<RoaringBitmap>) -> Vec<RoaringBitmap> { fn create_disjoint_combinations(parts_candidates_array: Vec<RoaringBitmap>) -> Vec<RoaringBitmap> {
let non_disjoint_combinations = create_non_disjoint_combinations(parts_candidates_array); let non_disjoint_combinations = create_non_disjoint_combinations(parts_candidates_array);
let mut disjoint_combinations = vec![]; let mut disjoint_combinations = vec![];
let mut forbidden = RoaringBitmap::new(); let mut combinations = non_disjoint_combinations.into_iter().peekable();
for mut combination in non_disjoint_combinations.into_iter().rev() { while let Some(mut combination) = combinations.next() {
combination -= &forbidden; if let Some(forbidden) = combinations.peek() {
forbidden |= &combination; combination -= forbidden;
}
disjoint_combinations.push(combination) disjoint_combinations.push(combination)
} }
disjoint_combinations.reverse();
disjoint_combinations disjoint_combinations
} }