Skip to main content

luci/query/
constant_score.rs

1//! ConstantScoreQuery: wrap a query with a fixed score.
2//!
3//! Runs the inner query in filter context and returns a constant score
4//! for all matching documents.
5//!
6//! See [[query-dsl#Compound Queries]] and [[architecture-query-execution#Step 6]].
7
8use crate::core::{DocId, Result, ScoreMode, Scorer, TwoPhaseIterator};
9
10use crate::query::{BoundQuery, Query, ScorerSupplier};
11use crate::search::searcher::Searcher;
12use crate::segment::reader::SegmentReader;
13
14pub struct ConstantScoreQuery {
15    pub(crate) inner: Box<dyn Query>,
16    pub boost: f32,
17}
18
19impl Query for ConstantScoreQuery {
20    fn bind(&self, searcher: &Searcher, _score_mode: ScoreMode) -> Result<Box<dyn BoundQuery>> {
21        // Inner query runs in filter context
22        let inner_weight = self.inner.bind(searcher, ScoreMode::CompleteNoScores)?;
23        Ok(Box::new(BoundConstantScoreQuery {
24            inner: inner_weight,
25            boost: self.boost,
26        }))
27    }
28}
29
30struct BoundConstantScoreQuery {
31    inner: Box<dyn BoundQuery>,
32    boost: f32,
33}
34
35impl BoundQuery for BoundConstantScoreQuery {
36    fn scorer_supplier(&self, reader: &SegmentReader) -> Result<Option<Box<dyn ScorerSupplier>>> {
37        match self.inner.scorer_supplier(reader)? {
38            Some(supplier) => Ok(Some(Box::new(ConstantScoreScorerSupplier {
39                inner: supplier,
40                boost: self.boost,
41            }))),
42            None => Ok(None),
43        }
44    }
45}
46
47struct ConstantScoreScorerSupplier {
48    inner: Box<dyn ScorerSupplier>,
49    boost: f32,
50}
51
52unsafe impl Send for ConstantScoreScorerSupplier {}
53
54impl ScorerSupplier for ConstantScoreScorerSupplier {
55    fn cost(&self) -> u64 {
56        self.inner.cost()
57    }
58
59    fn scorer(self: Box<Self>) -> Result<Box<dyn Scorer>> {
60        let inner = self.inner.scorer()?;
61        Ok(Box::new(ConstantScoreScorer {
62            inner,
63            boost: self.boost,
64        }))
65    }
66}
67
68struct ConstantScoreScorer {
69    inner: Box<dyn Scorer>,
70    boost: f32,
71}
72
73impl Scorer for ConstantScoreScorer {
74    fn doc_id(&self) -> DocId {
75        self.inner.doc_id()
76    }
77    fn next(&mut self) -> DocId {
78        self.inner.next()
79    }
80    fn advance(&mut self, target: DocId) -> DocId {
81        self.inner.advance(target)
82    }
83    fn score(&mut self) -> f32 {
84        self.boost
85    }
86    fn two_phase(&mut self) -> Option<&mut dyn TwoPhaseIterator> {
87        self.inner.two_phase()
88    }
89}