use crate::core::{DocId, Result, ScoreMode, Scorer, TwoPhaseIterator};
use crate::query::{BoundQuery, Query, ScorerSupplier};
use crate::search::searcher::Searcher;
use crate::segment::reader::SegmentReader;
pub struct BoostQuery {
pub(crate) inner: Box<dyn Query>,
pub boost: f32,
}
impl Query for BoostQuery {
fn bind(&self, searcher: &Searcher, score_mode: ScoreMode) -> Result<Box<dyn BoundQuery>> {
let inner = self.inner.bind(searcher, score_mode)?;
Ok(Box::new(BoundBoostQuery {
inner,
boost: self.boost,
}))
}
}
struct BoundBoostQuery {
inner: Box<dyn BoundQuery>,
boost: f32,
}
impl BoundQuery for BoundBoostQuery {
fn scorer_supplier(&self, reader: &SegmentReader) -> Result<Option<Box<dyn ScorerSupplier>>> {
let inner = match self.inner.scorer_supplier(reader)? {
Some(s) => s,
None => return Ok(None),
};
Ok(Some(Box::new(BoostScorerSupplier {
inner,
boost: self.boost,
})))
}
}
struct BoostScorerSupplier {
inner: Box<dyn ScorerSupplier>,
boost: f32,
}
impl ScorerSupplier for BoostScorerSupplier {
fn cost(&self) -> u64 {
self.inner.cost()
}
fn scorer(self: Box<Self>) -> Result<Box<dyn Scorer>> {
let inner = self.inner.scorer()?;
Ok(Box::new(BoostScorer {
inner,
boost: self.boost,
}))
}
}
struct BoostScorer {
inner: Box<dyn Scorer>,
boost: f32,
}
impl Scorer for BoostScorer {
fn doc_id(&self) -> DocId {
self.inner.doc_id()
}
fn next(&mut self) -> DocId {
self.inner.next()
}
fn advance(&mut self, target: DocId) -> DocId {
self.inner.advance(target)
}
fn score(&mut self) -> f32 {
self.inner.score() * self.boost
}
fn two_phase(&mut self) -> Option<&mut dyn TwoPhaseIterator> {
None
}
fn max_score(&self) -> f32 {
self.inner.max_score() * self.boost
}
fn set_min_competitive_score(&mut self, min_score: f32) {
if self.boost > 0.0 {
self.inner.set_min_competitive_score(min_score / self.boost);
}
}
}