use crate::core::{Result, ScoreMode, Scorer};
use crate::query::{BoundQuery, Query, ScorerSupplier};
use crate::search::searcher::Searcher;
use crate::segment::reader::SegmentReader;
pub struct DisMaxQuery {
pub(crate) queries: Vec<Box<dyn Query>>,
pub tie_breaker: f32,
}
impl Query for DisMaxQuery {
fn bind(&self, searcher: &Searcher, score_mode: ScoreMode) -> Result<Box<dyn BoundQuery>> {
let weights: Vec<Box<dyn BoundQuery>> = self
.queries
.iter()
.map(|q| q.bind(searcher, score_mode))
.collect::<Result<_>>()?;
Ok(Box::new(BoundDisMaxQuery {
weights,
tie_breaker: self.tie_breaker,
}))
}
}
struct BoundDisMaxQuery {
weights: Vec<Box<dyn BoundQuery>>,
tie_breaker: f32,
}
impl BoundQuery for BoundDisMaxQuery {
fn scorer_supplier(&self, reader: &SegmentReader) -> Result<Option<Box<dyn ScorerSupplier>>> {
let mut suppliers: Vec<Box<dyn ScorerSupplier>> = Vec::new();
for w in &self.weights {
if let Some(s) = w.scorer_supplier(reader)? {
suppliers.push(s);
}
}
if suppliers.is_empty() {
return Ok(None);
}
Ok(Some(Box::new(DisMaxScorerSupplier {
suppliers,
tie_breaker: self.tie_breaker,
})))
}
}
struct DisMaxScorerSupplier {
suppliers: Vec<Box<dyn ScorerSupplier>>,
tie_breaker: f32,
}
impl ScorerSupplier for DisMaxScorerSupplier {
fn cost(&self) -> u64 {
self.suppliers.iter().map(|s| s.cost()).sum()
}
fn scorer(self: Box<Self>) -> Result<Box<dyn Scorer>> {
let scorers: Vec<Box<dyn Scorer>> = self
.suppliers
.into_iter()
.map(|s| s.scorer())
.collect::<Result<_>>()?;
Ok(Box::new(crate::search::wand::WANDScorer::new_dis_max(
scorers,
self.tie_breaker,
)))
}
}
#[cfg(test)]
mod tests {
#[test]
fn dis_max_score_computation() {
}
}