diff --git a/src/query/boolean_query/boolean_clause.rs b/src/query/boolean_query/boolean_clause.rs deleted file mode 100644 index e2e2a55b6..000000000 --- a/src/query/boolean_query/boolean_clause.rs +++ /dev/null @@ -1,18 +0,0 @@ -use query::Occur; -use query::Query; - -#[derive(Debug)] -pub struct BooleanClause { - pub query: Box, - pub occur: Occur, -} - - -impl BooleanClause { - pub fn new(query: Box, occur: Occur) -> BooleanClause { - BooleanClause { - query: query, - occur: occur, - } - } -} \ No newline at end of file diff --git a/src/query/boolean_query/boolean_query.rs b/src/query/boolean_query/boolean_query.rs index 195bbf20c..2d660f7aa 100644 --- a/src/query/boolean_query/boolean_query.rs +++ b/src/query/boolean_query/boolean_query.rs @@ -1,7 +1,6 @@ use Result; use std::any::Any; use super::boolean_weight::BooleanWeight; -use super::BooleanClause; use query::Weight; use Searcher; use query::Query; @@ -20,12 +19,12 @@ use query::OccurFilter; /// a `MustNot` occurence. #[derive(Debug)] pub struct BooleanQuery { - clauses: Vec, + subqueries: Vec<(Occur, Box)> } -impl From> for BooleanQuery { - fn from(clauses: Vec) -> BooleanQuery { - BooleanQuery { clauses: clauses } +impl From)>> for BooleanQuery { + fn from(subqueries: Vec<(Occur, Box)>) -> BooleanQuery { + BooleanQuery { subqueries: subqueries } } } @@ -35,13 +34,13 @@ impl Query for BooleanQuery { } fn weight(&self, searcher: &Searcher) -> Result> { - let sub_weights = try!(self.clauses + let sub_weights = try!(self.subqueries .iter() - .map(|clause| clause.query.weight(searcher)) + .map(|&(ref _occur, ref subquery)| subquery.weight(searcher)) .collect()); - let occurs: Vec = self.clauses + let occurs: Vec = self.subqueries .iter() - .map(|clause| clause.occur) + .map(|&(ref occur, ref _subquery)| *occur) .collect(); let filter = OccurFilter::new(&occurs); Ok(box BooleanWeight::new(sub_weights, filter)) diff --git a/src/query/boolean_query/mod.rs b/src/query/boolean_query/mod.rs index 43d0e3336..36a113b7f 100644 --- a/src/query/boolean_query/mod.rs +++ b/src/query/boolean_query/mod.rs @@ -1,11 +1,9 @@ -mod boolean_clause; mod boolean_query; mod boolean_scorer; mod boolean_weight; mod score_combiner; pub use self::boolean_query::BooleanQuery; -pub use self::boolean_clause::BooleanClause; pub use self::boolean_scorer::BooleanScorer; pub use self::score_combiner::ScoreCombiner; @@ -20,12 +18,93 @@ mod tests { use query::OccurFilter; use query::term_query::TermScorer; use query::Occur; + use query::Query; + use query::TermQuery; + use collector::tests::TestCollector; + use Index; + use schema::*; use fastfield::{U32FastFieldReader}; fn abs_diff(left: f32, right: f32) -> f32 { (right - left).abs() } + + #[test] + pub fn test_boolean_query() { + let mut schema_builder = SchemaBuilder::default(); + let text_field = schema_builder.add_text_field("text", TEXT); + let schema = schema_builder.build(); + let index = Index::create_from_tempdir(schema).unwrap(); + { + // writing the segment + let mut index_writer = index.writer_with_num_threads(1, 40_000_000).unwrap(); + { + let doc = doc!(text_field => "a b c"); + index_writer.add_document(doc).unwrap(); + } + { + let doc = doc!(text_field => "a c"); + index_writer.add_document(doc).unwrap(); + } + { + let doc = doc!(text_field => "b c"); + index_writer.add_document(doc).unwrap(); + } + { + let doc = doc!(text_field => "a b c d"); + index_writer.add_document(doc).unwrap(); + } + { + let doc = doc!(text_field => "d"); + index_writer.add_document(doc).unwrap(); + } + assert!(index_writer.commit().is_ok()); + } + let make_term_query = |text: &str| { + let term_query = TermQuery::from(Term::from_field_text(text_field, text)); + let query: Box = box term_query; + query + }; + + + let matching_docs = |boolean_query: &Query| { + let searcher = index.searcher(); + let mut test_collector = TestCollector::default(); + boolean_query.search(&*searcher, &mut test_collector).unwrap(); + test_collector.docs() + }; + { + let boolean_query = BooleanQuery::from(vec![(Occur::Must, make_term_query("a")) ]); + assert_eq!(matching_docs(&boolean_query), vec!(0, 1, 3)); + } + { + let boolean_query = BooleanQuery::from(vec![(Occur::Should, make_term_query("a")) ]); + assert_eq!(matching_docs(&boolean_query), vec!(0, 1, 3)); + } + { + let boolean_query = BooleanQuery::from(vec![(Occur::Should, make_term_query("a")), (Occur::Should, make_term_query("b"))]); + assert_eq!(matching_docs(&boolean_query), vec!(0, 1, 2, 3)); + } + { + let boolean_query = BooleanQuery::from(vec![(Occur::Must, make_term_query("a")), (Occur::Should, make_term_query("b"))]); + assert_eq!(matching_docs(&boolean_query), vec!(0, 1, 3)); + } + { + let boolean_query = BooleanQuery::from(vec![(Occur::Must, make_term_query("a")), + (Occur::Should, make_term_query("b")), + (Occur::MustNot, make_term_query("d")), + ]); + assert_eq!(matching_docs(&boolean_query), vec!(0, 1)); + } + { + let boolean_query = BooleanQuery::from(vec![(Occur::MustNot, make_term_query("d")),]); + // TODO optimize this use case : only MustNot subqueries... no need + // to read any postings. + assert_eq!(matching_docs(&boolean_query), Vec::new()); + } + } + #[test] pub fn test_boolean_scorer() { let occurs = vec!(Occur::Should, Occur::Should);