mirror of
				https://github.com/meilisearch/meilisearch.git
				synced 2025-11-03 17:36:29 +00:00 
			
		
		
		
	Allow the search cache to store owned values
This commit is contained in:
		@@ -57,7 +57,6 @@ fn main() -> Result<(), Box<dyn Error>> {
 | 
				
			|||||||
                false,
 | 
					                false,
 | 
				
			||||||
                &None,
 | 
					                &None,
 | 
				
			||||||
                &None,
 | 
					                &None,
 | 
				
			||||||
                None,
 | 
					 | 
				
			||||||
                GeoSortStrategy::default(),
 | 
					                GeoSortStrategy::default(),
 | 
				
			||||||
                0,
 | 
					                0,
 | 
				
			||||||
                20,
 | 
					                20,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,6 +117,11 @@ impl<'a> Search<'a> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn execute(&self) -> Result<SearchResult> {
 | 
					    pub fn execute(&self) -> Result<SearchResult> {
 | 
				
			||||||
        let mut ctx = SearchContext::new(self.index, self.rtxn);
 | 
					        let mut ctx = SearchContext::new(self.index, self.rtxn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let Some(searchable_attributes) = self.searchable_attributes {
 | 
				
			||||||
 | 
					            ctx.searchable_attributes(searchable_attributes)?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let PartialSearchResult { located_query_terms, candidates, documents_ids, document_scores } =
 | 
					        let PartialSearchResult { located_query_terms, candidates, documents_ids, document_scores } =
 | 
				
			||||||
            execute_search(
 | 
					            execute_search(
 | 
				
			||||||
                &mut ctx,
 | 
					                &mut ctx,
 | 
				
			||||||
@@ -126,7 +131,6 @@ impl<'a> Search<'a> {
 | 
				
			|||||||
                self.exhaustive_number_hits,
 | 
					                self.exhaustive_number_hits,
 | 
				
			||||||
                &self.filter,
 | 
					                &self.filter,
 | 
				
			||||||
                &self.sort_criteria,
 | 
					                &self.sort_criteria,
 | 
				
			||||||
                self.searchable_attributes,
 | 
					 | 
				
			||||||
                self.geo_strategy,
 | 
					                self.geo_strategy,
 | 
				
			||||||
                self.offset,
 | 
					                self.offset,
 | 
				
			||||||
                self.limit,
 | 
					                self.limit,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,12 +4,13 @@ use std::hash::Hash;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use fxhash::FxHashMap;
 | 
					use fxhash::FxHashMap;
 | 
				
			||||||
use heed::types::ByteSlice;
 | 
					use heed::types::ByteSlice;
 | 
				
			||||||
use heed::{BytesDecode, BytesEncode, Database, RoTxn};
 | 
					use heed::{BytesEncode, Database, RoTxn};
 | 
				
			||||||
use roaring::RoaringBitmap;
 | 
					use roaring::RoaringBitmap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::interner::Interned;
 | 
					use super::interner::Interned;
 | 
				
			||||||
use super::Word;
 | 
					use super::Word;
 | 
				
			||||||
use crate::heed_codec::StrBEU16Codec;
 | 
					use crate::heed_codec::{BytesDecodeOwned, StrBEU16Codec};
 | 
				
			||||||
 | 
					use crate::update::MergeFn;
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    CboRoaringBitmapCodec, CboRoaringBitmapLenCodec, Result, RoaringBitmapCodec, SearchContext,
 | 
					    CboRoaringBitmapCodec, CboRoaringBitmapLenCodec, Result, RoaringBitmapCodec, SearchContext,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -22,48 +23,106 @@ use crate::{
 | 
				
			|||||||
#[derive(Default)]
 | 
					#[derive(Default)]
 | 
				
			||||||
pub struct DatabaseCache<'ctx> {
 | 
					pub struct DatabaseCache<'ctx> {
 | 
				
			||||||
    pub word_pair_proximity_docids:
 | 
					    pub word_pair_proximity_docids:
 | 
				
			||||||
        FxHashMap<(u8, Interned<String>, Interned<String>), Option<&'ctx [u8]>>,
 | 
					        FxHashMap<(u8, Interned<String>, Interned<String>), Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_prefix_pair_proximity_docids:
 | 
					    pub word_prefix_pair_proximity_docids:
 | 
				
			||||||
        FxHashMap<(u8, Interned<String>, Interned<String>), Option<&'ctx [u8]>>,
 | 
					        FxHashMap<(u8, Interned<String>, Interned<String>), Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub prefix_word_pair_proximity_docids:
 | 
					    pub prefix_word_pair_proximity_docids:
 | 
				
			||||||
        FxHashMap<(u8, Interned<String>, Interned<String>), Option<&'ctx [u8]>>,
 | 
					        FxHashMap<(u8, Interned<String>, Interned<String>), Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_docids: FxHashMap<Interned<String>, Option<&'ctx [u8]>>,
 | 
					    pub word_docids: FxHashMap<Interned<String>, Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub exact_word_docids: FxHashMap<Interned<String>, Option<&'ctx [u8]>>,
 | 
					    pub exact_word_docids: FxHashMap<Interned<String>, Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_prefix_docids: FxHashMap<Interned<String>, Option<&'ctx [u8]>>,
 | 
					    pub word_prefix_docids: FxHashMap<Interned<String>, Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub exact_word_prefix_docids: FxHashMap<Interned<String>, Option<&'ctx [u8]>>,
 | 
					    pub exact_word_prefix_docids: FxHashMap<Interned<String>, Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub words_fst: Option<fst::Set<Cow<'ctx, [u8]>>>,
 | 
					    pub words_fst: Option<fst::Set<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_position_docids: FxHashMap<(Interned<String>, u16), Option<&'ctx [u8]>>,
 | 
					    pub word_position_docids: FxHashMap<(Interned<String>, u16), Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_prefix_position_docids: FxHashMap<(Interned<String>, u16), Option<&'ctx [u8]>>,
 | 
					    pub word_prefix_position_docids: FxHashMap<(Interned<String>, u16), Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_positions: FxHashMap<Interned<String>, Vec<u16>>,
 | 
					    pub word_positions: FxHashMap<Interned<String>, Vec<u16>>,
 | 
				
			||||||
    pub word_prefix_positions: FxHashMap<Interned<String>, Vec<u16>>,
 | 
					    pub word_prefix_positions: FxHashMap<Interned<String>, Vec<u16>>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub word_fid_docids: FxHashMap<(Interned<String>, u16), Option<&'ctx [u8]>>,
 | 
					    pub word_fid_docids: FxHashMap<(Interned<String>, u16), Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_prefix_fid_docids: FxHashMap<(Interned<String>, u16), Option<&'ctx [u8]>>,
 | 
					    pub word_prefix_fid_docids: FxHashMap<(Interned<String>, u16), Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
    pub word_fids: FxHashMap<Interned<String>, Vec<u16>>,
 | 
					    pub word_fids: FxHashMap<Interned<String>, Vec<u16>>,
 | 
				
			||||||
    pub word_prefix_fids: FxHashMap<Interned<String>, Vec<u16>>,
 | 
					    pub word_prefix_fids: FxHashMap<Interned<String>, Vec<u16>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
impl<'ctx> DatabaseCache<'ctx> {
 | 
					impl<'ctx> DatabaseCache<'ctx> {
 | 
				
			||||||
    fn get_value<'v, K1, KC>(
 | 
					    fn get_value<'v, K1, KC, DC>(
 | 
				
			||||||
        txn: &'ctx RoTxn,
 | 
					        txn: &'ctx RoTxn,
 | 
				
			||||||
        cache_key: K1,
 | 
					        cache_key: K1,
 | 
				
			||||||
        db_key: &'v KC::EItem,
 | 
					        db_key: &'v KC::EItem,
 | 
				
			||||||
        cache: &mut FxHashMap<K1, Option<&'ctx [u8]>>,
 | 
					        cache: &mut FxHashMap<K1, Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
        db: Database<KC, ByteSlice>,
 | 
					        db: Database<KC, ByteSlice>,
 | 
				
			||||||
    ) -> Result<Option<&'ctx [u8]>>
 | 
					    ) -> Result<Option<DC::DItem>>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        K1: Copy + Eq + Hash,
 | 
					        K1: Copy + Eq + Hash,
 | 
				
			||||||
        KC: BytesEncode<'v>,
 | 
					        KC: BytesEncode<'v>,
 | 
				
			||||||
 | 
					        DC: BytesDecodeOwned,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let bitmap_ptr = match cache.entry(cache_key) {
 | 
					        match cache.entry(cache_key) {
 | 
				
			||||||
            Entry::Occupied(bitmap_ptr) => *bitmap_ptr.get(),
 | 
					            Entry::Occupied(_) => {}
 | 
				
			||||||
            Entry::Vacant(entry) => {
 | 
					            Entry::Vacant(entry) => {
 | 
				
			||||||
                let bitmap_ptr = db.get(txn, db_key)?;
 | 
					                let bitmap_ptr = db.get(txn, db_key)?.map(Cow::Borrowed);
 | 
				
			||||||
 | 
					                entry.insert(bitmap_ptr);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match cache.get(&cache_key).unwrap() {
 | 
				
			||||||
 | 
					            Some(Cow::Borrowed(bytes)) => {
 | 
				
			||||||
 | 
					                DC::bytes_decode_owned(bytes).ok_or(heed::Error::Decoding.into()).map(Some)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Some(Cow::Owned(bytes)) => {
 | 
				
			||||||
 | 
					                DC::bytes_decode_owned(bytes).ok_or(heed::Error::Decoding.into()).map(Some)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            None => Ok(None),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn get_value_from_keys<'v, K1, KC, DC>(
 | 
				
			||||||
 | 
					        txn: &'ctx RoTxn,
 | 
				
			||||||
 | 
					        cache_key: K1,
 | 
				
			||||||
 | 
					        db_keys: &[&'v KC::EItem],
 | 
				
			||||||
 | 
					        cache: &mut FxHashMap<K1, Option<Cow<'ctx, [u8]>>>,
 | 
				
			||||||
 | 
					        db: Database<KC, ByteSlice>,
 | 
				
			||||||
 | 
					        merger: MergeFn,
 | 
				
			||||||
 | 
					    ) -> Result<Option<DC::DItem>>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        K1: Copy + Eq + Hash,
 | 
				
			||||||
 | 
					        KC: BytesEncode<'v>,
 | 
				
			||||||
 | 
					        DC: BytesDecodeOwned,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        match cache.entry(cache_key) {
 | 
				
			||||||
 | 
					            Entry::Occupied(_) => {}
 | 
				
			||||||
 | 
					            Entry::Vacant(entry) => {
 | 
				
			||||||
 | 
					                let bitmap_ptr: Option<Cow<'ctx, [u8]>> = match db_keys {
 | 
				
			||||||
 | 
					                    [] => None,
 | 
				
			||||||
 | 
					                    [key] => db.get(txn, key)?.map(Cow::Borrowed),
 | 
				
			||||||
 | 
					                    keys => {
 | 
				
			||||||
 | 
					                        let bitmaps = keys
 | 
				
			||||||
 | 
					                            .into_iter()
 | 
				
			||||||
 | 
					                            .filter_map(|key| db.get(txn, key).transpose())
 | 
				
			||||||
 | 
					                            .map(|v| v.map(Cow::Borrowed))
 | 
				
			||||||
 | 
					                            .collect::<std::result::Result<Vec<Cow<[u8]>>, _>>()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if bitmaps.is_empty() {
 | 
				
			||||||
 | 
					                            None
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            Some(merger(&[], &bitmaps[..])?)
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                entry.insert(bitmap_ptr);
 | 
					                entry.insert(bitmap_ptr);
 | 
				
			||||||
                bitmap_ptr
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        Ok(bitmap_ptr)
 | 
					
 | 
				
			||||||
 | 
					        match cache.get(&cache_key).unwrap() {
 | 
				
			||||||
 | 
					            Some(Cow::Borrowed(bytes)) => {
 | 
				
			||||||
 | 
					                DC::bytes_decode_owned(bytes).ok_or(heed::Error::Decoding.into()).map(Some)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Some(Cow::Owned(bytes)) => {
 | 
				
			||||||
 | 
					                DC::bytes_decode_owned(bytes).ok_or(heed::Error::Decoding.into()).map(Some)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            None => Ok(None),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
impl<'ctx> SearchContext<'ctx> {
 | 
					impl<'ctx> SearchContext<'ctx> {
 | 
				
			||||||
@@ -99,30 +158,26 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Retrieve or insert the given value in the `word_docids` database.
 | 
					    /// Retrieve or insert the given value in the `word_docids` database.
 | 
				
			||||||
    fn get_db_word_docids(&mut self, word: Interned<String>) -> Result<Option<RoaringBitmap>> {
 | 
					    fn get_db_word_docids(&mut self, word: Interned<String>) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, RoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            word,
 | 
					            word,
 | 
				
			||||||
            self.word_interner.get(word).as_str(),
 | 
					            self.word_interner.get(word).as_str(),
 | 
				
			||||||
            &mut self.db_cache.word_docids,
 | 
					            &mut self.db_cache.word_docids,
 | 
				
			||||||
            self.index.word_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| RoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn get_db_exact_word_docids(
 | 
					    fn get_db_exact_word_docids(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        word: Interned<String>,
 | 
					        word: Interned<String>,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, RoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            word,
 | 
					            word,
 | 
				
			||||||
            self.word_interner.get(word).as_str(),
 | 
					            self.word_interner.get(word).as_str(),
 | 
				
			||||||
            &mut self.db_cache.exact_word_docids,
 | 
					            &mut self.db_cache.exact_word_docids,
 | 
				
			||||||
            self.index.exact_word_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.exact_word_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| RoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn word_prefix_docids(&mut self, prefix: Word) -> Result<Option<RoaringBitmap>> {
 | 
					    pub fn word_prefix_docids(&mut self, prefix: Word) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
@@ -150,30 +205,26 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        prefix: Interned<String>,
 | 
					        prefix: Interned<String>,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, RoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            prefix,
 | 
					            prefix,
 | 
				
			||||||
            self.word_interner.get(prefix).as_str(),
 | 
					            self.word_interner.get(prefix).as_str(),
 | 
				
			||||||
            &mut self.db_cache.word_prefix_docids,
 | 
					            &mut self.db_cache.word_prefix_docids,
 | 
				
			||||||
            self.index.word_prefix_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_prefix_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| RoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn get_db_exact_word_prefix_docids(
 | 
					    fn get_db_exact_word_prefix_docids(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
        prefix: Interned<String>,
 | 
					        prefix: Interned<String>,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, RoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            prefix,
 | 
					            prefix,
 | 
				
			||||||
            self.word_interner.get(prefix).as_str(),
 | 
					            self.word_interner.get(prefix).as_str(),
 | 
				
			||||||
            &mut self.db_cache.exact_word_prefix_docids,
 | 
					            &mut self.db_cache.exact_word_prefix_docids,
 | 
				
			||||||
            self.index.exact_word_prefix_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.exact_word_prefix_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| RoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_pair_proximity_docids(
 | 
					    pub fn get_db_word_pair_proximity_docids(
 | 
				
			||||||
@@ -182,7 +233,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        word2: Interned<String>,
 | 
					        word2: Interned<String>,
 | 
				
			||||||
        proximity: u8,
 | 
					        proximity: u8,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (proximity, word1, word2),
 | 
					            (proximity, word1, word2),
 | 
				
			||||||
            &(
 | 
					            &(
 | 
				
			||||||
@@ -192,9 +243,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
            &mut self.db_cache.word_pair_proximity_docids,
 | 
					            &mut self.db_cache.word_pair_proximity_docids,
 | 
				
			||||||
            self.index.word_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| CboRoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_pair_proximity_docids_len(
 | 
					    pub fn get_db_word_pair_proximity_docids_len(
 | 
				
			||||||
@@ -203,7 +252,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        word2: Interned<String>,
 | 
					        word2: Interned<String>,
 | 
				
			||||||
        proximity: u8,
 | 
					        proximity: u8,
 | 
				
			||||||
    ) -> Result<Option<u64>> {
 | 
					    ) -> Result<Option<u64>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapLenCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (proximity, word1, word2),
 | 
					            (proximity, word1, word2),
 | 
				
			||||||
            &(
 | 
					            &(
 | 
				
			||||||
@@ -213,11 +262,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
            &mut self.db_cache.word_pair_proximity_docids,
 | 
					            &mut self.db_cache.word_pair_proximity_docids,
 | 
				
			||||||
            self.index.word_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| {
 | 
					 | 
				
			||||||
            CboRoaringBitmapLenCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into())
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_prefix_pair_proximity_docids(
 | 
					    pub fn get_db_word_prefix_pair_proximity_docids(
 | 
				
			||||||
@@ -226,7 +271,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        prefix2: Interned<String>,
 | 
					        prefix2: Interned<String>,
 | 
				
			||||||
        proximity: u8,
 | 
					        proximity: u8,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (proximity, word1, prefix2),
 | 
					            (proximity, word1, prefix2),
 | 
				
			||||||
            &(
 | 
					            &(
 | 
				
			||||||
@@ -236,9 +281,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
            &mut self.db_cache.word_prefix_pair_proximity_docids,
 | 
					            &mut self.db_cache.word_prefix_pair_proximity_docids,
 | 
				
			||||||
            self.index.word_prefix_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_prefix_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| CboRoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn get_db_prefix_word_pair_proximity_docids(
 | 
					    pub fn get_db_prefix_word_pair_proximity_docids(
 | 
				
			||||||
        &mut self,
 | 
					        &mut self,
 | 
				
			||||||
@@ -246,7 +289,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        right: Interned<String>,
 | 
					        right: Interned<String>,
 | 
				
			||||||
        proximity: u8,
 | 
					        proximity: u8,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (proximity, left_prefix, right),
 | 
					            (proximity, left_prefix, right),
 | 
				
			||||||
            &(
 | 
					            &(
 | 
				
			||||||
@@ -256,9 +299,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
            &mut self.db_cache.prefix_word_pair_proximity_docids,
 | 
					            &mut self.db_cache.prefix_word_pair_proximity_docids,
 | 
				
			||||||
            self.index.prefix_word_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.prefix_word_pair_proximity_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| CboRoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_fid_docids(
 | 
					    pub fn get_db_word_fid_docids(
 | 
				
			||||||
@@ -266,15 +307,13 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        word: Interned<String>,
 | 
					        word: Interned<String>,
 | 
				
			||||||
        fid: u16,
 | 
					        fid: u16,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (word, fid),
 | 
					            (word, fid),
 | 
				
			||||||
            &(self.word_interner.get(word).as_str(), fid),
 | 
					            &(self.word_interner.get(word).as_str(), fid),
 | 
				
			||||||
            &mut self.db_cache.word_fid_docids,
 | 
					            &mut self.db_cache.word_fid_docids,
 | 
				
			||||||
            self.index.word_fid_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_fid_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| CboRoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_prefix_fid_docids(
 | 
					    pub fn get_db_word_prefix_fid_docids(
 | 
				
			||||||
@@ -282,15 +321,13 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        word_prefix: Interned<String>,
 | 
					        word_prefix: Interned<String>,
 | 
				
			||||||
        fid: u16,
 | 
					        fid: u16,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (word_prefix, fid),
 | 
					            (word_prefix, fid),
 | 
				
			||||||
            &(self.word_interner.get(word_prefix).as_str(), fid),
 | 
					            &(self.word_interner.get(word_prefix).as_str(), fid),
 | 
				
			||||||
            &mut self.db_cache.word_prefix_fid_docids,
 | 
					            &mut self.db_cache.word_prefix_fid_docids,
 | 
				
			||||||
            self.index.word_prefix_fid_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_prefix_fid_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| CboRoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_fids(&mut self, word: Interned<String>) -> Result<Vec<u16>> {
 | 
					    pub fn get_db_word_fids(&mut self, word: Interned<String>) -> Result<Vec<u16>> {
 | 
				
			||||||
@@ -309,7 +346,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
                for result in remap_key_type {
 | 
					                for result in remap_key_type {
 | 
				
			||||||
                    let ((_, fid), value) = result?;
 | 
					                    let ((_, fid), value) = result?;
 | 
				
			||||||
                    // filling other caches to avoid searching for them again
 | 
					                    // filling other caches to avoid searching for them again
 | 
				
			||||||
                    self.db_cache.word_fid_docids.insert((word, fid), Some(value));
 | 
					                    self.db_cache.word_fid_docids.insert((word, fid), Some(Cow::Borrowed(value)));
 | 
				
			||||||
                    fids.push(fid);
 | 
					                    fids.push(fid);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                entry.insert(fids.clone());
 | 
					                entry.insert(fids.clone());
 | 
				
			||||||
@@ -335,7 +372,9 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
                for result in remap_key_type {
 | 
					                for result in remap_key_type {
 | 
				
			||||||
                    let ((_, fid), value) = result?;
 | 
					                    let ((_, fid), value) = result?;
 | 
				
			||||||
                    // filling other caches to avoid searching for them again
 | 
					                    // filling other caches to avoid searching for them again
 | 
				
			||||||
                    self.db_cache.word_prefix_fid_docids.insert((word_prefix, fid), Some(value));
 | 
					                    self.db_cache
 | 
				
			||||||
 | 
					                        .word_prefix_fid_docids
 | 
				
			||||||
 | 
					                        .insert((word_prefix, fid), Some(Cow::Borrowed(value)));
 | 
				
			||||||
                    fids.push(fid);
 | 
					                    fids.push(fid);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                entry.insert(fids.clone());
 | 
					                entry.insert(fids.clone());
 | 
				
			||||||
@@ -350,15 +389,13 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        word: Interned<String>,
 | 
					        word: Interned<String>,
 | 
				
			||||||
        position: u16,
 | 
					        position: u16,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (word, position),
 | 
					            (word, position),
 | 
				
			||||||
            &(self.word_interner.get(word).as_str(), position),
 | 
					            &(self.word_interner.get(word).as_str(), position),
 | 
				
			||||||
            &mut self.db_cache.word_position_docids,
 | 
					            &mut self.db_cache.word_position_docids,
 | 
				
			||||||
            self.index.word_position_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_position_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| CboRoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_prefix_position_docids(
 | 
					    pub fn get_db_word_prefix_position_docids(
 | 
				
			||||||
@@ -366,15 +403,13 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
        word_prefix: Interned<String>,
 | 
					        word_prefix: Interned<String>,
 | 
				
			||||||
        position: u16,
 | 
					        position: u16,
 | 
				
			||||||
    ) -> Result<Option<RoaringBitmap>> {
 | 
					    ) -> Result<Option<RoaringBitmap>> {
 | 
				
			||||||
        DatabaseCache::get_value(
 | 
					        DatabaseCache::get_value::<_, _, CboRoaringBitmapCodec>(
 | 
				
			||||||
            self.txn,
 | 
					            self.txn,
 | 
				
			||||||
            (word_prefix, position),
 | 
					            (word_prefix, position),
 | 
				
			||||||
            &(self.word_interner.get(word_prefix).as_str(), position),
 | 
					            &(self.word_interner.get(word_prefix).as_str(), position),
 | 
				
			||||||
            &mut self.db_cache.word_prefix_position_docids,
 | 
					            &mut self.db_cache.word_prefix_position_docids,
 | 
				
			||||||
            self.index.word_prefix_position_docids.remap_data_type::<ByteSlice>(),
 | 
					            self.index.word_prefix_position_docids.remap_data_type::<ByteSlice>(),
 | 
				
			||||||
        )?
 | 
					        )
 | 
				
			||||||
        .map(|bytes| CboRoaringBitmapCodec::bytes_decode(bytes).ok_or(heed::Error::Decoding.into()))
 | 
					 | 
				
			||||||
        .transpose()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_db_word_positions(&mut self, word: Interned<String>) -> Result<Vec<u16>> {
 | 
					    pub fn get_db_word_positions(&mut self, word: Interned<String>) -> Result<Vec<u16>> {
 | 
				
			||||||
@@ -393,7 +428,9 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
                for result in remap_key_type {
 | 
					                for result in remap_key_type {
 | 
				
			||||||
                    let ((_, position), value) = result?;
 | 
					                    let ((_, position), value) = result?;
 | 
				
			||||||
                    // filling other caches to avoid searching for them again
 | 
					                    // filling other caches to avoid searching for them again
 | 
				
			||||||
                    self.db_cache.word_position_docids.insert((word, position), Some(value));
 | 
					                    self.db_cache
 | 
				
			||||||
 | 
					                        .word_position_docids
 | 
				
			||||||
 | 
					                        .insert((word, position), Some(Cow::Borrowed(value)));
 | 
				
			||||||
                    positions.push(position);
 | 
					                    positions.push(position);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                entry.insert(positions.clone());
 | 
					                entry.insert(positions.clone());
 | 
				
			||||||
@@ -424,7 +461,7 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
                    // filling other caches to avoid searching for them again
 | 
					                    // filling other caches to avoid searching for them again
 | 
				
			||||||
                    self.db_cache
 | 
					                    self.db_cache
 | 
				
			||||||
                        .word_prefix_position_docids
 | 
					                        .word_prefix_position_docids
 | 
				
			||||||
                        .insert((word_prefix, position), Some(value));
 | 
					                        .insert((word_prefix, position), Some(Cow::Borrowed(value)));
 | 
				
			||||||
                    positions.push(position);
 | 
					                    positions.push(position);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                entry.insert(positions.clone());
 | 
					                entry.insert(positions.clone());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -514,7 +514,6 @@ mod tests {
 | 
				
			|||||||
                false,
 | 
					                false,
 | 
				
			||||||
                &None,
 | 
					                &None,
 | 
				
			||||||
                &None,
 | 
					                &None,
 | 
				
			||||||
                None,
 | 
					 | 
				
			||||||
                crate::search::new::GeoSortStrategy::default(),
 | 
					                crate::search::new::GeoSortStrategy::default(),
 | 
				
			||||||
                0,
 | 
					                0,
 | 
				
			||||||
                100,
 | 
					                100,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,6 +57,7 @@ pub struct SearchContext<'ctx> {
 | 
				
			|||||||
    pub phrase_interner: DedupInterner<Phrase>,
 | 
					    pub phrase_interner: DedupInterner<Phrase>,
 | 
				
			||||||
    pub term_interner: Interner<QueryTerm>,
 | 
					    pub term_interner: Interner<QueryTerm>,
 | 
				
			||||||
    pub phrase_docids: PhraseDocIdsCache,
 | 
					    pub phrase_docids: PhraseDocIdsCache,
 | 
				
			||||||
 | 
					    pub restricted_fids: Option<Vec<u16>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'ctx> SearchContext<'ctx> {
 | 
					impl<'ctx> SearchContext<'ctx> {
 | 
				
			||||||
@@ -69,8 +70,18 @@ impl<'ctx> SearchContext<'ctx> {
 | 
				
			|||||||
            phrase_interner: <_>::default(),
 | 
					            phrase_interner: <_>::default(),
 | 
				
			||||||
            term_interner: <_>::default(),
 | 
					            term_interner: <_>::default(),
 | 
				
			||||||
            phrase_docids: <_>::default(),
 | 
					            phrase_docids: <_>::default(),
 | 
				
			||||||
 | 
					            restricted_fids: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn searchable_attributes(&mut self, searchable_attributes: &'ctx [String]) -> Result<()> {
 | 
				
			||||||
 | 
					        let fids_map = self.index.fields_ids_map(&self.txn)?;
 | 
				
			||||||
 | 
					        let restricted_fids =
 | 
				
			||||||
 | 
					            searchable_attributes.iter().filter_map(|name| fids_map.id(name)).collect();
 | 
				
			||||||
 | 
					        self.restricted_fids = Some(restricted_fids);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
 | 
					#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
 | 
				
			||||||
@@ -355,7 +366,6 @@ pub fn execute_search(
 | 
				
			|||||||
    exhaustive_number_hits: bool,
 | 
					    exhaustive_number_hits: bool,
 | 
				
			||||||
    filters: &Option<Filter>,
 | 
					    filters: &Option<Filter>,
 | 
				
			||||||
    sort_criteria: &Option<Vec<AscDesc>>,
 | 
					    sort_criteria: &Option<Vec<AscDesc>>,
 | 
				
			||||||
    searchable_attributes: Option<&[String]>,
 | 
					 | 
				
			||||||
    geo_strategy: geo_sort::Strategy,
 | 
					    geo_strategy: geo_sort::Strategy,
 | 
				
			||||||
    from: usize,
 | 
					    from: usize,
 | 
				
			||||||
    length: usize,
 | 
					    length: usize,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,8 @@ pub use self::delete_documents::{DeleteDocuments, DeletionStrategy, DocumentDele
 | 
				
			|||||||
pub use self::facet::bulk::FacetsUpdateBulk;
 | 
					pub use self::facet::bulk::FacetsUpdateBulk;
 | 
				
			||||||
pub use self::facet::incremental::FacetsUpdateIncrementalInner;
 | 
					pub use self::facet::incremental::FacetsUpdateIncrementalInner;
 | 
				
			||||||
pub use self::index_documents::{
 | 
					pub use self::index_documents::{
 | 
				
			||||||
    DocumentAdditionResult, DocumentId, IndexDocuments, IndexDocumentsConfig, IndexDocumentsMethod,
 | 
					    merge_roaring_bitmaps, DocumentAdditionResult, DocumentId, IndexDocuments,
 | 
				
			||||||
 | 
					    IndexDocumentsConfig, IndexDocumentsMethod, MergeFn,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
pub use self::indexer_config::IndexerConfig;
 | 
					pub use self::indexer_config::IndexerConfig;
 | 
				
			||||||
pub use self::prefix_word_pairs::{
 | 
					pub use self::prefix_word_pairs::{
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user