mirror of
https://github.com/quickwit-oss/tantivy.git
synced 2026-05-31 07:30:39 +00:00
Query optimization: phrase query + union
This commit is contained in:
@@ -51,6 +51,9 @@ impl Query for BooleanQuery {
|
||||
|
||||
fn disable_scoring(&mut self) {
|
||||
self.scoring_disabled = true;
|
||||
for &mut (_, ref mut subquery) in &mut self.subqueries {
|
||||
subquery.disable_scoring();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use query::Weight;
|
||||
use core::SegmentReader;
|
||||
use postings::{IntersectionDocSet, UnionDocSet};
|
||||
use std::collections::HashMap;
|
||||
use query::EmptyScorer;
|
||||
use query::Scorer;
|
||||
use super::BooleanScorer;
|
||||
use query::OccurFilter;
|
||||
use query::ConstScorer;
|
||||
use query::Occur;
|
||||
use Result;
|
||||
|
||||
@@ -33,19 +36,54 @@ impl Weight for BooleanWeight {
|
||||
weight.scorer(reader)
|
||||
}
|
||||
} else {
|
||||
let sub_scorers: Vec<Box<Scorer + 'a>> = self.weights
|
||||
.iter()
|
||||
.map(|&(_, ref weight)| weight)
|
||||
.map(|weight| weight.scorer(reader))
|
||||
.collect::<Result<_>>()?;
|
||||
let occurs: Vec<Occur> = self.weights
|
||||
.iter()
|
||||
.map(|&(ref occur, _)| *occur)
|
||||
.collect();
|
||||
let occur_filter = OccurFilter::new(&occurs);
|
||||
let boolean_scorer = BooleanScorer::new(sub_scorers, occur_filter);
|
||||
Ok(box boolean_scorer)
|
||||
}
|
||||
if self.scoring_disabled {
|
||||
let mut per_occur_scorers = HashMap::new();
|
||||
for &(ref occur, ref subweight) in &self.weights {
|
||||
per_occur_scorers
|
||||
.entry(occur)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(subweight.scorer(reader)?);
|
||||
}
|
||||
let mut result_scorer_opt: Option<Box<Scorer>> = per_occur_scorers
|
||||
.remove(&Occur::Should)
|
||||
.map(|subscorers| {
|
||||
assert!(!subscorers.is_empty());
|
||||
if subscorers.len() == 1 {
|
||||
subscorers
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap() //< we checked the size beforehands
|
||||
} else {
|
||||
box ConstScorer::new(UnionDocSet::from(subscorers))
|
||||
}
|
||||
});
|
||||
if let Some(mut subscorers) = per_occur_scorers.remove(&Occur::Must) {
|
||||
if let Some(should_query) = result_scorer_opt {
|
||||
subscorers.push(should_query);
|
||||
}
|
||||
let intersection_docset = IntersectionDocSet::from(subscorers);
|
||||
result_scorer_opt = Some(box ConstScorer::new(intersection_docset));
|
||||
}
|
||||
|
||||
if let Some(result_scorer) = result_scorer_opt {
|
||||
Ok(result_scorer)
|
||||
} else {
|
||||
Ok(box EmptyScorer)
|
||||
}
|
||||
} else {
|
||||
let sub_scorers: Vec<Box<Scorer + 'a>> = self.weights
|
||||
.iter()
|
||||
.map(|&(_, ref weight)| weight)
|
||||
.map(|weight| weight.scorer(reader))
|
||||
.collect::<Result<_>>()?;
|
||||
let occurs: Vec<Occur> = self.weights
|
||||
.iter()
|
||||
.map(|&(ref occur, _)| *occur)
|
||||
.collect();
|
||||
let occur_filter = OccurFilter::new(&occurs);
|
||||
let boolean_scorer = BooleanScorer::new(sub_scorers, occur_filter);
|
||||
Ok(box boolean_scorer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user