use std::collections::BTreeSet;
use std::path::Path;
use super::BM25Index;
impl BM25Index {
pub fn remove_chunks_with_prefix(&mut self, prefix: &str) -> usize {
self.remove_chunks_of(|source| source.starts_with(prefix))
}
pub(super) fn evict_sources(root: &Path, gone: &BTreeSet<String>) -> usize {
let _write = super::persist_lock();
let Some(mut persisted) = Self::load(root) else {
return 0;
};
let removed = persisted.remove_chunks_of(|source| gone.contains(source));
if removed == 0 {
return 0;
}
for source in gone {
persisted.files.remove(source);
}
if persisted.save(root).is_ok() {
removed
} else {
0
}
}
pub(crate) fn remove_sources(&mut self, sources: &std::collections::HashSet<&str>) -> usize {
self.remove_chunks_of(|source| sources.contains(source))
}
fn remove_chunks_of(&mut self, evicted: impl Fn(&str) -> bool) -> usize {
let mut kept = 0usize;
let positions: Vec<Option<usize>> = self
.chunks
.iter()
.map(|chunk| {
if evicted(&chunk.file_path) {
None
} else {
kept += 1;
Some(kept - 1)
}
})
.collect();
let removed = positions.len() - kept;
if removed == 0 {
return 0;
}
self.chunks.retain(|c| !evicted(&c.file_path));
self.inverted.retain(|_, postings| {
postings.retain_mut(|(idx, _)| match positions.get(*idx).copied().flatten() {
Some(position) => {
*idx = position;
true
}
None => false,
});
!postings.is_empty()
});
self.doc_freqs = self
.inverted
.iter()
.map(|(term, postings)| {
let mut documents = 0usize;
let mut last = None;
for (idx, _) in postings {
if last != Some(*idx) {
documents += 1;
last = Some(*idx);
}
}
(term.clone(), documents)
})
.collect();
self.finalize();
removed
}
}