lucisearch 0.8.1

Embeddable, in-process search engine — the SQLite/DuckDB of search
Documentation
//! ConstantScoreQuery: wrap a query with a fixed score.
//!
//! Runs the inner query in filter context and returns a constant score
//! for all matching documents.
//!
//! See [[query-dsl#Compound Queries]] and [[architecture-query-execution#Step 6]].

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 ConstantScoreQuery {
    pub(crate) inner: Box<dyn Query>,
    pub boost: f32,
}

impl Query for ConstantScoreQuery {
    fn bind(&self, searcher: &Searcher, _score_mode: ScoreMode) -> Result<Box<dyn BoundQuery>> {
        // Inner query runs in filter context
        let inner_weight = self.inner.bind(searcher, ScoreMode::CompleteNoScores)?;
        Ok(Box::new(BoundConstantScoreQuery {
            inner: inner_weight,
            boost: self.boost,
        }))
    }
}

struct BoundConstantScoreQuery {
    inner: Box<dyn BoundQuery>,
    boost: f32,
}

impl BoundQuery for BoundConstantScoreQuery {
    fn scorer_supplier(&self, reader: &SegmentReader) -> Result<Option<Box<dyn ScorerSupplier>>> {
        match self.inner.scorer_supplier(reader)? {
            Some(supplier) => Ok(Some(Box::new(ConstantScoreScorerSupplier {
                inner: supplier,
                boost: self.boost,
            }))),
            None => Ok(None),
        }
    }
}

struct ConstantScoreScorerSupplier {
    inner: Box<dyn ScorerSupplier>,
    boost: f32,
}

unsafe impl Send for ConstantScoreScorerSupplier {}

impl ScorerSupplier for ConstantScoreScorerSupplier {
    fn cost(&self) -> u64 {
        self.inner.cost()
    }

    fn scorer(self: Box<Self>) -> Result<Box<dyn Scorer>> {
        let inner = self.inner.scorer()?;
        Ok(Box::new(ConstantScoreScorer {
            inner,
            boost: self.boost,
        }))
    }
}

struct ConstantScoreScorer {
    inner: Box<dyn Scorer>,
    boost: f32,
}

impl Scorer for ConstantScoreScorer {
    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.boost
    }
    fn two_phase(&mut self) -> Option<&mut dyn TwoPhaseIterator> {
        self.inner.two_phase()
    }
}