mirror of
https://github.com/quickwit-oss/tantivy.git
synced 2026-10-06 20:02:45 +00:00
* Add DocPredicateQuery and a generic FunctionPredicate implementation Introduces the DocPredicate/SegmentDocPredicate abstraction and DocPredicateQuery, a query that walks a segment's documents by repeatedly evaluating a per-segment predicate (with a scorer_danger fast path for boolean intersections). FunctionPredicate is a first, generic implementation built from a plain per-segment factory function, with no dependency on fast fields or any other segment data structure. * CR comments * Better explain
74 lines
2.2 KiB
Rust
74 lines
2.2 KiB
Rust
use super::{DocPredicate, SegmentDocPredicate};
|
|
use crate::index::SegmentReader;
|
|
use crate::DocId;
|
|
|
|
/// Blanket [`SegmentDocPredicate`] implementation for any per-document
|
|
/// function.
|
|
impl<F> SegmentDocPredicate for F
|
|
where F: Fn(DocId) -> bool + Send + Sync + 'static
|
|
{
|
|
fn eval(&mut self, doc_id: DocId) -> bool {
|
|
(self)(doc_id)
|
|
}
|
|
}
|
|
|
|
/// A [`DocPredicate`] built from a plain factory function.
|
|
///
|
|
/// `FunctionPredicate` wraps a factory closure that is called once per
|
|
/// segment (via [`DocPredicate::doc_predicate`]) and returns a per-document
|
|
/// closure evaluated once per candidate document.
|
|
pub struct FunctionPredicate<F> {
|
|
segment_predicate_factory: F,
|
|
}
|
|
|
|
impl<F, SegmentF> From<F> for FunctionPredicate<F>
|
|
where
|
|
F: Fn(&SegmentReader) -> crate::Result<SegmentF> + Send + 'static,
|
|
SegmentF: SegmentDocPredicate,
|
|
{
|
|
fn from(segment_predicate_factory: F) -> Self {
|
|
Self {
|
|
segment_predicate_factory,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<F> std::fmt::Debug for FunctionPredicate<F> {
|
|
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
formatter
|
|
.debug_struct("FunctionPredicate")
|
|
.finish_non_exhaustive()
|
|
}
|
|
}
|
|
|
|
impl<F, SegmentF> DocPredicate for FunctionPredicate<F>
|
|
where
|
|
F: Fn(&SegmentReader) -> crate::Result<SegmentF> + Send + Sync + 'static,
|
|
SegmentF: SegmentDocPredicate,
|
|
{
|
|
type SegmentDocPredicate = SegmentF;
|
|
|
|
fn doc_predicate(&self, segment_reader: &SegmentReader) -> crate::Result<SegmentF> {
|
|
(self.segment_predicate_factory)(segment_reader)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::collector::Count;
|
|
use crate::query::doc_predicate_query::tests::create_index_for_test;
|
|
use crate::query::doc_predicate_query::DocPredicateQuery;
|
|
|
|
#[test]
|
|
fn test_function_predicate_matches_even_doc_ids() {
|
|
let index = create_index_for_test(4);
|
|
let searcher = index.reader().unwrap().searcher();
|
|
let predicate = FunctionPredicate::from(|_segment_reader: &SegmentReader| {
|
|
Ok(move |doc_id: DocId| doc_id % 2 == 0)
|
|
});
|
|
let query: DocPredicateQuery = predicate.into();
|
|
assert_eq!(searcher.search(&query, &Count).unwrap(), 2);
|
|
}
|
|
}
|