Add support for sorting by float features
The search is now feature complete, I think.
- Id
- 34962f711dffa5bb3dc5d757ac85d654655d5e83
- Author
- Caio
- Commit time
- 2019-12-11T11:01:04+01:00
Modified crates/cantine/src/index.rs
use tique::{
queryparser::QueryParser,
- top_collector::{ordered_by_u64_fast_field, ConditionalTopCollector, SearchMarker},
+ top_collector::{
+ ordered_by_f64_fast_field, ordered_by_u64_fast_field, ConditionalTopCollector, SearchMarker,
+ },
};
#[derive(Clone)]
}};
}
+ macro_rules! collect_float {
+ ($field:ident) => {{
+ let condition = condition_from_score!(after.score_f64());
+ let top_collector =
+ ordered_by_f64_fast_field(self.fields.features.$field, limit, condition);
+
+ let result = searcher.search(interpreted_query, &top_collector)?;
+ let items = self.addresses_to_ids(&searcher, &result.items)?;
+
+ let num_items = items.len();
+ let cursor = if result.visited.saturating_sub(num_items) > 0 {
+ let last_score = result.items[num_items - 1].score;
+ let last_id = items[num_items - 1];
+ Some(SearchCursor::from_f64(last_score, last_id))
+ } else {
+ None
+ };
+
+ Ok((result.total, items, cursor))
+ }};
+ }
+
match sort {
Sort::Relevance => {
let condition = condition_from_score!(after.score_f32());
Ok((result.total, items, cursor))
}
- Sort::Calories => collect_unsigned!(calories),
Sort::NumIngredients => collect_unsigned!(num_ingredients),
Sort::InstructionsLength => collect_unsigned!(instructions_length),
Sort::TotalTime => collect_unsigned!(total_time),
Sort::CookTime => collect_unsigned!(cook_time),
Sort::PrepTime => collect_unsigned!(prep_time),
- _ => unimplemented!(),
+ Sort::Calories => collect_unsigned!(calories),
+ Sort::FatContent => collect_float!(fat_content),
+ Sort::CarbContent => collect_float!(carbohydrate_content),
+ Sort::ProteinContent => collect_float!(protein_content),
}
}
Modified crates/cantine/src/model.rs
Self(score.to_bits() as u64, recipe_id)
}
+ pub fn from_f64(score: f64, recipe_id: RecipeId) -> Self {
+ Self(score.to_bits(), recipe_id)
+ }
+
pub fn is_start(&self) -> bool {
self.0 == 0 && self.1 == 0
}
pub fn score_f32(&self) -> f32 {
f32::from_bits(self.0 as u32)
+ }
+
+ pub fn score_f64(&self) -> f64 {
+ f64::from_bits(self.0)
}
}
Modified crates/cantine/tests/index_integration.rs
Ok(())
}
+
+#[test]
+fn float_field_sorting() -> Result<()> {
+ let reader = GLOBAL.index.reader()?;
+ let searcher = reader.searcher();
+
+ let (_total, found_ids, _next) = GLOBAL.cantine.search(
+ &searcher,
+ &AllQuery,
+ INDEX_SIZE,
+ Sort::ProteinContent,
+ SearchCursor::START,
+ )?;
+
+ let mut last_protein = std::f32::MAX;
+ for id in found_ids {
+ let recipe = GLOBAL.db.get(&id).unwrap();
+ if let Some(protein_content) = recipe.features.protein_content {
+ assert!(protein_content <= last_protein);
+ last_protein = protein_content;
+ }
+ }
+
+ assert_ne!(std::f32::MAX, last_protein);
+
+ Ok(())
+}