From 7720d212651282d6d9292a9657d6b234bb22ee79 Mon Sep 17 00:00:00 2001 From: Paul Masurel Date: Thu, 1 Oct 2020 20:25:28 +0900 Subject: [PATCH] Closes #896 - Facet reader related Bugfix. Acquiring a facet reader on a segment that does not contain any doc with this facet returns `None`. --- CHANGELOG.md | 5 ++ Cargo.toml | 2 +- examples/faceted_search_with_tweaked_score.rs | 2 +- src/core/segment_reader.rs | 6 ++- src/fastfield/facet_reader.rs | 47 ++++++++++++++++++- src/fastfield/writer.rs | 1 + src/indexer/segment_writer.rs | 2 +- 7 files changed, 59 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9e2cc728..d3fe9865b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +Tantivy 0.13.2 +=================== +Bugfix. Acquiring a facet reader on a segment that does not contain any +doc with this facet returns `None`. (#896) + Tantivy 0.13.1 ====================== Made `Query` and `Collector` `Send + Sync`. diff --git a/Cargo.toml b/Cargo.toml index ef551e8ad..0d031fa49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tantivy" -version = "0.13.1" +version = "0.13.2" authors = ["Paul Masurel "] license = "MIT" categories = ["database-implementations", "data-structures"] diff --git a/examples/faceted_search_with_tweaked_score.rs b/examples/faceted_search_with_tweaked_score.rs index ee493bd23..57331f822 100644 --- a/examples/faceted_search_with_tweaked_score.rs +++ b/examples/faceted_search_with_tweaked_score.rs @@ -56,7 +56,7 @@ fn main() -> tantivy::Result<()> { ); let top_docs_by_custom_score = TopDocs::with_limit(2).tweak_score(move |segment_reader: &SegmentReader| { - let mut ingredient_reader = segment_reader.facet_reader(ingredient).unwrap(); + let ingredient_reader = segment_reader.facet_reader(ingredient).unwrap(); let facet_dict = ingredient_reader.facet_dict(); let query_ords: HashSet = facets diff --git a/src/core/segment_reader.rs b/src/core/segment_reader.rs index ebd9ad3de..52b1dc565 100644 --- a/src/core/segment_reader.rs +++ b/src/core/segment_reader.rs @@ -112,8 +112,10 @@ impl SegmentReader { return None; } let term_ords_reader = self.fast_fields().u64s(field)?; - let termdict_source = self.termdict_composite.open_read(field)?; - let termdict = TermDictionary::from_source(&termdict_source); + let termdict = self.termdict_composite + .open_read(field) + .map(|source| TermDictionary::from_source(&source)) + .unwrap_or_else(TermDictionary::empty); let facet_reader = FacetReader::new(term_ords_reader, termdict); Some(facet_reader) } diff --git a/src/fastfield/facet_reader.rs b/src/fastfield/facet_reader.rs index 4bf8f3671..2d70d6377 100644 --- a/src/fastfield/facet_reader.rs +++ b/src/fastfield/facet_reader.rs @@ -73,7 +73,52 @@ impl FacetReader { } /// Return the list of facet ordinals associated to a document. - pub fn facet_ords(&mut self, doc: DocId, output: &mut Vec) { + pub fn facet_ords(&self, doc: DocId, output: &mut Vec) { self.term_ords.get_vals(doc, output); } } + +#[cfg(test)] +mod tests { + use crate::{Document, schema::{Facet, SchemaBuilder}}; + use crate::Index; + + #[test] + fn test_facet_not_populated_for_all_docs() -> crate::Result<()> { + let mut schema_builder = SchemaBuilder::default(); + let facet_field = schema_builder.add_facet_field("facet"); + 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)?; + index_writer.add_document(doc!(facet_field=>Facet::from_text("/a/b"))); + index_writer.add_document(Document::default()); + index_writer.commit()?; + let searcher = index.reader()?.searcher(); + let facet_reader = searcher.segment_reader(0u32).facet_reader(facet_field).unwrap(); + let mut facet_ords = Vec::new(); + facet_reader.facet_ords(0u32, &mut facet_ords); + assert_eq!(&facet_ords, &[2u64]); + facet_reader.facet_ords(1u32, &mut facet_ords); + assert!(facet_ords.is_empty()); + Ok(()) + } + #[test] + fn test_facet_not_populated_for_any_docs() -> crate::Result<()> { + let mut schema_builder = SchemaBuilder::default(); + let facet_field = schema_builder.add_facet_field("facet"); + 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)?; + index_writer.add_document(Document::default()); + index_writer.add_document(Document::default()); + index_writer.commit()?; + let searcher = index.reader()?.searcher(); + let facet_reader = searcher.segment_reader(0u32).facet_reader(facet_field).unwrap(); + let mut facet_ords = Vec::new(); + facet_reader.facet_ords(0u32, &mut facet_ords); + assert!(facet_ords.is_empty()); + facet_reader.facet_ords(1u32, &mut facet_ords); + assert!(facet_ords.is_empty()); + Ok(()) + } +} \ No newline at end of file diff --git a/src/fastfield/writer.rs b/src/fastfield/writer.rs index c841faa46..a4cca00c0 100644 --- a/src/fastfield/writer.rs +++ b/src/fastfield/writer.rs @@ -126,6 +126,7 @@ impl FastFieldsWriter { for field_writer in &self.single_value_writers { field_writer.serialize(serializer)?; } + for field_writer in &self.multi_values_writers { let field = field_writer.field(); field_writer.serialize(serializer, mapping.get(&field))?; diff --git a/src/indexer/segment_writer.rs b/src/indexer/segment_writer.rs index d56764b4f..eff52fb01 100644 --- a/src/indexer/segment_writer.rs +++ b/src/indexer/segment_writer.rs @@ -151,7 +151,7 @@ impl SegmentWriter { if let Some(unordered_term_id) = unordered_term_id_opt { self.fast_field_writers .get_multivalue_writer(field) - .expect("multified writer for facet missing") + .expect("writer for facet missing") .add_val(unordered_term_id); } }