1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use core::Searcher;
use core::SegmentReader;
use docset::DocSet;
use query::{Query, Scorer, Weight};
use DocId;
use Result;
use Score;

/// Query that matches all of the documents.
///
/// All of the document get the score 1f32.
#[derive(Clone, Debug)]
pub struct AllQuery;

impl Query for AllQuery {
    fn weight(&self, _: &Searcher, _: bool) -> Result<Box<Weight>> {
        Ok(Box::new(AllWeight))
    }
}

/// Weight associated to the `AllQuery` query.
pub struct AllWeight;

impl Weight for AllWeight {
    fn scorer(&self, reader: &SegmentReader) -> Result<Box<Scorer>> {
        Ok(Box::new(AllScorer {
            state: State::NotStarted,
            doc: 0u32,
            max_doc: reader.max_doc(),
        }))
    }
}

enum State {
    NotStarted,
    Started,
    Finished,
}

/// Scorer associated to the `AllQuery` query.
pub struct AllScorer {
    state: State,
    doc: DocId,
    max_doc: DocId,
}

impl DocSet for AllScorer {
    fn advance(&mut self) -> bool {
        match self.state {
            State::NotStarted => {
                self.state = State::Started;
                self.doc = 0;
            }
            State::Started => {
                self.doc += 1u32;
            }
            State::Finished => {
                return false;
            }
        }
        if self.doc < self.max_doc {
            true
        } else {
            self.state = State::Finished;
            false
        }
    }

    fn doc(&self) -> DocId {
        self.doc
    }

    fn size_hint(&self) -> u32 {
        self.max_doc
    }
}

impl Scorer for AllScorer {
    fn score(&mut self) -> Score {
        1f32
    }
}

#[cfg(test)]
mod tests {

    use super::AllQuery;
    use query::Query;
    use schema::{Schema, TEXT};
    use Index;

    #[test]
    fn test_all_query() {
        let mut schema_builder = Schema::builder();
        let field = schema_builder.add_text_field("text", TEXT);
        let schema = schema_builder.build();
        let index = Index::create_in_ram(schema);
        let mut index_writer = index.writer_with_num_threads(1, 10_000_000).unwrap();
        index_writer.add_document(doc!(field=>"aaa"));
        index_writer.add_document(doc!(field=>"bbb"));
        index_writer.commit().unwrap();
        index_writer.add_document(doc!(field=>"ccc"));
        index_writer.commit().unwrap();
        index.load_searchers().unwrap();
        let searcher = index.searcher();
        let weight = AllQuery.weight(&searcher, false).unwrap();
        {
            let reader = searcher.segment_reader(0);
            let mut scorer = weight.scorer(reader).unwrap();
            assert!(scorer.advance());
            assert_eq!(scorer.doc(), 0u32);
            assert!(scorer.advance());
            assert_eq!(scorer.doc(), 1u32);
            assert!(!scorer.advance());
        }
        {
            let reader = searcher.segment_reader(1);
            let mut scorer = weight.scorer(reader).unwrap();
            assert!(scorer.advance());
            assert_eq!(scorer.doc(), 0u32);
            assert!(!scorer.advance());
        }
    }

}