use nodedb_types::Surrogate;
use crate::posting::Posting;
use crate::scope::IndexScope;
pub trait FtsBackend {
type Error: std::fmt::Display;
fn read_postings(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
term: &str,
) -> Result<Vec<Posting>, Self::Error>;
fn write_postings(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
term: &str,
postings: &[Posting],
) -> Result<(), Self::Error>;
fn remove_postings(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
term: &str,
) -> Result<(), Self::Error>;
fn upsert_posting(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
term: &str,
posting: &Posting,
) -> Result<(), Self::Error> {
let mut list = self.read_postings(database_id, tid, index, term)?;
match list.iter_mut().find(|p| p.doc_id == posting.doc_id) {
Some(slot) => slot.clone_from(posting),
None => list.push(posting.clone()),
}
self.write_postings(database_id, tid, index, term, &list)
}
fn remove_posting(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
term: &str,
doc_id: Surrogate,
) -> Result<(), Self::Error> {
let mut list = self.read_postings(database_id, tid, index, term)?;
let before = list.len();
list.retain(|p| p.doc_id != doc_id);
if list.len() == before {
return Ok(());
}
if list.is_empty() {
self.remove_postings(database_id, tid, index, term)
} else {
self.write_postings(database_id, tid, index, term, &list)
}
}
fn read_doc_length(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
doc_id: Surrogate,
) -> Result<Option<u32>, Self::Error>;
fn read_doc_lengths(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
doc_ids: &[Surrogate],
) -> Result<Vec<Option<u32>>, Self::Error> {
doc_ids
.iter()
.map(|doc_id| self.read_doc_length(database_id, tid, index, *doc_id))
.collect()
}
fn write_doc_length(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
doc_id: Surrogate,
length: u32,
) -> Result<(), Self::Error>;
fn remove_doc_length(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
doc_id: Surrogate,
) -> Result<(), Self::Error>;
fn collection_terms(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
) -> Result<Vec<String>, Self::Error>;
fn collection_stats(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
) -> Result<(u32, u64), Self::Error>;
fn increment_stats(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
doc_len: u32,
) -> Result<(), Self::Error>;
fn decrement_stats(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
doc_len: u32,
) -> Result<(), Self::Error>;
fn read_meta(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
subkey: &str,
) -> Result<Option<Vec<u8>>, Self::Error>;
fn write_meta(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
subkey: &str,
value: &[u8],
) -> Result<(), Self::Error>;
fn write_segment(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
segment_id: &str,
data: &[u8],
) -> Result<(), Self::Error>;
fn read_segment(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
segment_id: &str,
) -> Result<Option<Vec<u8>>, Self::Error>;
fn list_segments(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
) -> Result<Vec<String>, Self::Error>;
fn remove_segment(
&self,
database_id: u64,
tid: u64,
index: IndexScope<'_>,
segment_id: &str,
) -> Result<(), Self::Error>;
fn purge_collection(
&self,
database_id: u64,
tid: u64,
collection: &str,
) -> Result<usize, Self::Error>;
fn purge_tenant(&self, database_id: u64, tid: u64) -> Result<usize, Self::Error>;
}