///|
priv struct MatchAllWeight {}
///|
priv struct MatchAllScorer {
document_count : Int
mut current_doc : DocId
}
///|
pub struct MatchAllQuery {}
///|
pub fn MatchAllQuery::new() -> MatchAllQuery {
MatchAllQuery::{ }
}
///|
impl Scorer for MatchAllScorer with fn advance(self) {
Scorer::advance_to(self, DocId::new(self.current_doc.value + 1))
}
///|
impl Scorer for MatchAllScorer with fn advance_to(self, target) {
let candidate = if target.value < 0 { 0 } else { target.value }
if candidate < self.document_count {
self.current_doc = DocId::new(candidate)
true
} else {
self.current_doc = DocId::new(-1)
false
}
}
///|
impl Scorer for MatchAllScorer with fn doc(self) {
self.current_doc
}
///|
impl Scorer for MatchAllScorer with fn score(_self) {
1.0
}
///|
impl Weight for MatchAllWeight with fn scorer(_self, segment) {
MatchAllScorer::{
document_count: segment.doc_count(),
current_doc: DocId::new(-1),
}
as &Scorer
}
///|
pub impl Query for MatchAllQuery with fn weight(_self, _statistics) {
MatchAllWeight::{ } as &Weight
}
///|
pub struct ConstantScoreQuery {
query : &Query
score : Double
}
///|
pub fn ConstantScoreQuery::new(
query : &Query,
score : Double,
) -> ConstantScoreQuery {
{ query, score }
}
///|
priv struct ConstantScoreWeight {
child : &Weight
score : Double
}
///|
priv struct ConstantScoreScorer {
child : &Scorer
score_value : Double
}
///|
impl Scorer for ConstantScoreScorer with fn advance(self) {
self.child.advance()
}
///|
impl Scorer for ConstantScoreScorer with fn advance_to(self, target) {
self.child.advance_to(target)
}
///|
impl Scorer for ConstantScoreScorer with fn doc(self) {
self.child.doc()
}
///|
impl Scorer for ConstantScoreScorer with fn score(self) {
self.score_value
}
///|
impl Weight for ConstantScoreWeight with fn scorer(self, segment) {
ConstantScoreScorer::{
child: self.child.scorer(segment),
score_value: self.score,
}
as &Scorer
}
///|
pub impl Query for ConstantScoreQuery with fn weight(self, statistics) {
ConstantScoreWeight::{
child: self.query.weight(statistics),
score: self.score,
}
as &Weight
}
///|
pub struct TermSetQuery {
terms : ReadOnlyArray[Term]
score : Double
}
///|
pub fn TermSetQuery::new(terms : Array[Term]) -> TermSetQuery {
{ terms: ReadOnlyArray::from_array(terms.copy()), score: 1.0 }
}
///|
pub fn TermSetQuery::with_score(
self : TermSetQuery,
score : Double,
) -> TermSetQuery {
{ terms: self.terms, score }
}
///|
pub impl Query for TermSetQuery with fn weight(self, statistics) {
let clauses : Array[BooleanClause] = []
for term in self.terms {
clauses.push(BooleanClause::new(Should, TermQuery::new(term)))
}
Query::weight(
ConstantScoreQuery::new(BooleanQuery::new(clauses), self.score),
statistics,
)
}
///|
pub struct DisjunctionMaxQuery {
disjuncts : ReadOnlyArray[&Query]
tie_breaker : Double
}
///|
pub fn DisjunctionMaxQuery::new(
disjuncts : Array[&Query],
tie_breaker : Double,
) -> DisjunctionMaxQuery {
guard tie_breaker >= 0.0 && tie_breaker <= 1.0 else {
abort("disjunction-max tie breaker must be between zero and one")
}
{ disjuncts: ReadOnlyArray::from_array(disjuncts.copy()), tie_breaker }
}
///|
priv struct DisjunctionMaxWeight {
weights : ReadOnlyArray[&Weight]
tie_breaker : Double
}
///|
priv struct DisjunctionMaxScorer {
scorers : ReadOnlyArray[&Scorer]
tie_breaker : Double
mut current_doc : DocId
mut current_score : Double
}
///|
fn DisjunctionMaxScorer::seek(
self : DisjunctionMaxScorer,
target : DocId,
) -> Bool {
let mut candidate : DocId? = None
for scorer in self.scorers {
if scorer.advance_to(target) {
candidate = match candidate {
None => Some(scorer.doc())
Some(current) =>
Some(
if scorer.doc().value < current.value {
scorer.doc()
} else {
current
},
)
}
}
}
match candidate {
None => {
self.current_doc = DocId::new(-1)
self.current_score = 0.0
false
}
Some(doc_id) => {
let mut maximum = 0.0
let mut total = 0.0
for scorer in self.scorers {
if scorer.doc() == doc_id {
let score = scorer.score()
total += score
if score > maximum {
maximum = score
}
}
}
self.current_doc = doc_id
self.current_score = maximum + (total - maximum) * self.tie_breaker
true
}
}
}
///|
impl Scorer for DisjunctionMaxScorer with fn advance(self) {
self.seek(DocId::new(self.current_doc.value + 1))
}
///|
impl Scorer for DisjunctionMaxScorer with fn advance_to(self, target) {
if self.current_doc.value >= target.value {
true
} else {
self.seek(target)
}
}
///|
impl Scorer for DisjunctionMaxScorer with fn doc(self) {
self.current_doc
}
///|
impl Scorer for DisjunctionMaxScorer with fn score(self) {
self.current_score
}
///|
impl Weight for DisjunctionMaxWeight with fn scorer(self, segment) {
let scorers : Array[&Scorer] = []
for weight in self.weights {
scorers.push(weight.scorer(segment))
}
DisjunctionMaxScorer::{
scorers: ReadOnlyArray::from_array(scorers),
tie_breaker: self.tie_breaker,
current_doc: DocId::new(-1),
current_score: 0.0,
}
as &Scorer
}
///|
pub impl Query for DisjunctionMaxQuery with fn weight(self, statistics) {
let weights : Array[&Weight] = []
for disjunct in self.disjuncts {
weights.push(disjunct.weight(statistics))
}
DisjunctionMaxWeight::{
weights: ReadOnlyArray::from_array(weights),
tie_breaker: self.tie_breaker,
}
as &Weight
}