1use crate::core::{Result, ScoreMode, Scorer};
7
8use crate::query::{BoundQuery, Query, ScorerSupplier};
9use crate::search::searcher::Searcher;
10use crate::segment::reader::SegmentReader;
11
12pub struct DisMaxQuery {
14 pub(crate) queries: Vec<Box<dyn Query>>,
15 pub tie_breaker: f32,
16}
17
18impl Query for DisMaxQuery {
19 fn bind(&self, searcher: &Searcher, score_mode: ScoreMode) -> Result<Box<dyn BoundQuery>> {
20 let weights: Vec<Box<dyn BoundQuery>> = self
21 .queries
22 .iter()
23 .map(|q| q.bind(searcher, score_mode))
24 .collect::<Result<_>>()?;
25 Ok(Box::new(BoundDisMaxQuery {
26 weights,
27 tie_breaker: self.tie_breaker,
28 }))
29 }
30}
31
32struct BoundDisMaxQuery {
33 weights: Vec<Box<dyn BoundQuery>>,
34 tie_breaker: f32,
35}
36
37impl BoundQuery for BoundDisMaxQuery {
38 fn scorer_supplier(&self, reader: &SegmentReader) -> Result<Option<Box<dyn ScorerSupplier>>> {
39 let mut suppliers: Vec<Box<dyn ScorerSupplier>> = Vec::new();
40 for w in &self.weights {
41 if let Some(s) = w.scorer_supplier(reader)? {
42 suppliers.push(s);
43 }
44 }
45 if suppliers.is_empty() {
46 return Ok(None);
47 }
48 Ok(Some(Box::new(DisMaxScorerSupplier {
49 suppliers,
50 tie_breaker: self.tie_breaker,
51 })))
52 }
53}
54
55struct DisMaxScorerSupplier {
56 suppliers: Vec<Box<dyn ScorerSupplier>>,
57 tie_breaker: f32,
58}
59
60impl ScorerSupplier for DisMaxScorerSupplier {
61 fn cost(&self) -> u64 {
62 self.suppliers.iter().map(|s| s.cost()).sum()
63 }
64
65 fn scorer(self: Box<Self>) -> Result<Box<dyn Scorer>> {
66 let scorers: Vec<Box<dyn Scorer>> = self
67 .suppliers
68 .into_iter()
69 .map(|s| s.scorer())
70 .collect::<Result<_>>()?;
71 Ok(Box::new(crate::search::wand::WANDScorer::new_dis_max(
72 scorers,
73 self.tie_breaker,
74 )))
75 }
76}
77
78#[cfg(test)]
81mod tests {
82
83 #[test]
84 fn dis_max_score_computation() {
85 }
93}