Repository: meilisearch/meilisearch
File: milli/src/search/new/exact_attribute.rs (Rust)

Code before:
                if candidates.is_empty() {
                    return Ok(State::Empty(query_graph.clone()));
                }
            }
        }

        let candidates = candidates;

        if candidates.is_empty() {
            return Ok(State::Empty(query_graph.clone()));
        }

        let searchable_fields_ids = ctx.index.searchable_fields_ids(ctx.txn)?;

        let mut candidates_per_attribute = Vec::with_capacity(searchable_fields_ids.len());
        // then check that there exists at least one attribute that has all of the terms
        for fid in searchable_fields_ids {
            let mut intersection = MultiOps::intersection(
                words_positions
                    .iter()
                    .flat_map(|(words, ..)| words.iter())
                    // ignore stop words words in phrases
                    .flatten()
                    .map(|word| -> Result<_> {
                        Ok(ctx
                            .get_db_word_fid_docids(Some(universe), *word, fid)?
                            .unwrap_or_default())
                    }),
            )?;
            // TODO Why not doing this intersection in the MultiOps above?
            intersection &= &candidates;
            if !intersection.is_empty() {
                // Although not really worth it in terms of performance,
                // if would be good to put this in cache for the sake of consistency
                let candidates_with_exact_word_count = if count_all_positions < u8::MAX as usize {
                    let bitmap_bytes = ctx
                        .index
                        .field_id_word_count_docids
                        .remap_data_type::<Bytes>()
                        .get(ctx.txn, &(fid, count_all_positions as u8))?;

                    match bitmap_bytes {
                        Some(bytes) => {
                            CboRoaringBitmapCodec::intersection_with_serialized(bytes, universe)?
                        }
                        None => RoaringBitmap::default(),
                    }
                } else {
                    RoaringBitmap::default()
                };
                candidates_per_attribute.push(FieldCandidates {

Review comment (suggestion):
```suggestion
                            .get_db_word_fid_docids(Some(candidates), *word, fid)?
```

Code after:
                if candidates.is_empty() {
                    return Ok(State::Empty(query_graph.clone()));
                }
            }
        }

        let candidates = candidates;

        if candidates.is_empty() {
            return Ok(State::Empty(query_graph.clone()));
        }

        let searchable_fields_ids = ctx.index.searchable_fields_ids(ctx.txn)?;

        let mut candidates_per_attribute = Vec::with_capacity(searchable_fields_ids.len());
        // then check that there exists at least one attribute that has all of the terms
        for fid in searchable_fields_ids {
            let intersection = MultiOps::intersection(
                words_positions
                    .iter()
                    .flat_map(|(words, ..)| words.iter())
                    // ignore stop words words in phrases
                    .flatten()
                    .map(|word| -> Result<_> {
                        Ok(ctx
                            .get_db_word_fid_docids(Some(&candidates), *word, fid)?
                            .unwrap_or_default())
                    }),
            )?;
            if !intersection.is_empty() {
                // Although not really worth it in terms of performance,
                // if would be good to put this in cache for the sake of consistency
                let candidates_with_exact_word_count = if count_all_positions < u8::MAX as usize {
                    let bitmap_bytes = ctx
                        .index
                        .field_id_word_count_docids
                        .remap_data_type::<Bytes>()
                        .get(ctx.txn, &(fid, count_all_positions as u8))?;

                    match bitmap_bytes {
                        Some(bytes) => {
                            CboRoaringBitmapCodec::intersection_with_serialized(bytes, universe)?
                        }
                        None => RoaringBitmap::default(),
                    }
                } else {
                    RoaringBitmap::default()
                };
                candidates_per_attribute.push(FieldCandidates {
                    start_with_exact: intersection,
                    exact_word_count: candidates_with_exact_word_count,