Query optimization: phrase query + union

This commit is contained in:
Paul Masurel
2018-02-02 16:39:17 +09:00
parent dd8332c327
commit fb5476d5de
8 changed files with 231 additions and 14 deletions

View File

@@ -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();
}
}
}

View File

@@ -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)
}
}
}
}