Skip to main content

luci/query/
boost.rs

1//! Boost wrapper: multiplies inner query's score by a constant factor.
2//!
3//! Applied automatically by the parser when any query has a `boost` parameter.
4
5use crate::core::{DocId, Result, ScoreMode, Scorer, TwoPhaseIterator};
6
7use crate::query::{BoundQuery, Query, ScorerSupplier};
8use crate::search::searcher::Searcher;
9use crate::segment::reader::SegmentReader;
10
11pub struct BoostQuery {
12    pub(crate) inner: Box<dyn Query>,
13    pub boost: f32,
14}
15
16impl Query for BoostQuery {
17    fn bind(&self, searcher: &Searcher, score_mode: ScoreMode) -> Result<Box<dyn BoundQuery>> {
18        let inner = self.inner.bind(searcher, score_mode)?;
19        Ok(Box::new(BoundBoostQuery {
20            inner,
21            boost: self.boost,
22        }))
23    }
24}
25
26struct BoundBoostQuery {
27    inner: Box<dyn BoundQuery>,
28    boost: f32,
29}
30
31impl BoundQuery for BoundBoostQuery {
32    fn scorer_supplier(&self, reader: &SegmentReader) -> Result<Option<Box<dyn ScorerSupplier>>> {
33        let inner = match self.inner.scorer_supplier(reader)? {
34            Some(s) => s,
35            None => return Ok(None),
36        };
37        Ok(Some(Box::new(BoostScorerSupplier {
38            inner,
39            boost: self.boost,
40        })))
41    }
42}
43
44struct BoostScorerSupplier {
45    inner: Box<dyn ScorerSupplier>,
46    boost: f32,
47}
48
49impl ScorerSupplier for BoostScorerSupplier {
50    fn cost(&self) -> u64 {
51        self.inner.cost()
52    }
53    fn scorer(self: Box<Self>) -> Result<Box<dyn Scorer>> {
54        let inner = self.inner.scorer()?;
55        Ok(Box::new(BoostScorer {
56            inner,
57            boost: self.boost,
58        }))
59    }
60}
61
62struct BoostScorer {
63    inner: Box<dyn Scorer>,
64    boost: f32,
65}
66
67impl Scorer for BoostScorer {
68    fn doc_id(&self) -> DocId {
69        self.inner.doc_id()
70    }
71    fn next(&mut self) -> DocId {
72        self.inner.next()
73    }
74    fn advance(&mut self, target: DocId) -> DocId {
75        self.inner.advance(target)
76    }
77    fn score(&mut self) -> f32 {
78        self.inner.score() * self.boost
79    }
80    fn two_phase(&mut self) -> Option<&mut dyn TwoPhaseIterator> {
81        None
82    }
83
84    fn max_score(&self) -> f32 {
85        self.inner.max_score() * self.boost
86    }
87    fn set_min_competitive_score(&mut self, min_score: f32) {
88        if self.boost > 0.0 {
89            self.inner.set_min_competitive_score(min_score / self.boost);
90        }
91    }
92}