From d615f89c5625af88193f2581263f1cbc7dd721ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Mon, 10 Dec 2018 12:10:59 +0100 Subject: [PATCH] feat: Introduce the SortBy help structure This structure help ranking documents using stored attributes. --- src/rank/criterion/document_id.rs | 19 ++++++++ src/rank/criterion/mod.rs | 69 +++++++++++++++++++++++++++ src/rank/criterion/sort_by.rs | 77 +++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 src/rank/criterion/document_id.rs create mode 100644 src/rank/criterion/sort_by.rs diff --git a/src/rank/criterion/document_id.rs b/src/rank/criterion/document_id.rs new file mode 100644 index 000000000..2d8ca34c2 --- /dev/null +++ b/src/rank/criterion/document_id.rs @@ -0,0 +1,19 @@ +use std::cmp::Ordering; +use std::ops::Deref; + +use rocksdb::DB; + +use crate::rank::criterion::Criterion; +use crate::database::DatabaseView; +use crate::rank::Document; + +#[derive(Debug, Clone, Copy)] +pub struct DocumentId; + +impl Criterion for DocumentId +where D: Deref +{ + fn evaluate(&self, lhs: &Document, rhs: &Document, _: &DatabaseView) -> Ordering { + lhs.id.cmp(&rhs.id) + } +} diff --git a/src/rank/criterion/mod.rs b/src/rank/criterion/mod.rs index 7ba34ce2b..3d8598608 100644 --- a/src/rank/criterion/mod.rs +++ b/src/rank/criterion/mod.rs @@ -7,7 +7,9 @@ mod exact; use std::cmp::Ordering; use std::ops::Deref; +use std::marker; +use serde::de::DeserializeOwned; use rocksdb::DB; use crate::database::DatabaseView; @@ -69,6 +71,73 @@ where D: Deref } } +/// An helper struct that permit to sort documents by +/// some of their stored attributes. +/// +/// # Note +/// +/// If a document cannot be deserialized it will be considered [`None`][]. +/// +/// Deserialized documents are compared like `Some(doc0).cmp(&Some(doc1))`, +/// so you must check the [`Ord`] of `Option` implementation. +/// +/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None +/// [`Ord`]: https://doc.rust-lang.org/std/option/enum.Option.html#impl-Ord +/// +/// # Example +/// +/// ``` +/// use serde_derive::Deserialize; +/// use meilidb::rank::criterion::*; +/// +/// #[derive(Deserialize, PartialOrd, Ord, PartialEq, Eq)] +/// struct TimeOnly { +/// time: String, +/// } +/// +/// let builder = CriteriaBuilder::with_capacity(7) +/// .add(SumOfTypos) +/// .add(NumberOfWords) +/// .add(WordsProximity) +/// .add(SumOfWordsAttribute) +/// .add(SumOfWordsPosition) +/// .add(Exact) +/// .add(SortBy::::new()) +/// .add(DocumentId); +/// +/// let criterion = builder.build(); +/// +/// ``` +#[derive(Default)] +pub struct SortBy { + _phantom: marker::PhantomData, +} + +impl SortBy { + pub fn new() -> Self { + SortBy { _phantom: marker::PhantomData } + } +} + +impl Criterion for SortBy +where D: Deref, + T: DeserializeOwned + Ord, +{ + fn evaluate(&self, lhs: &Document, rhs: &Document, view: &DatabaseView) -> Ordering { + let lhs = match view.retrieve_document::(lhs.id) { + Ok(doc) => Some(doc), + Err(e) => { eprintln!("{}", e); None }, + }; + + let rhs = match view.retrieve_document::(rhs.id) { + Ok(doc) => Some(doc), + Err(e) => { eprintln!("{}", e); None }, + }; + + lhs.cmp(&rhs) + } +} + pub struct CriteriaBuilder where D: Deref { diff --git a/src/rank/criterion/sort_by.rs b/src/rank/criterion/sort_by.rs new file mode 100644 index 000000000..7f60962aa --- /dev/null +++ b/src/rank/criterion/sort_by.rs @@ -0,0 +1,77 @@ +use std::cmp::Ordering; +use std::ops::Deref; +use std::marker; + +use rocksdb::DB; +use serde::de::DeserializeOwned; + +use crate::rank::criterion::Criterion; +use crate::database::DatabaseView; +use crate::rank::Document; + +/// An helper struct that permit to sort documents by +/// some of their stored attributes. +/// +/// # Note +/// +/// If a document cannot be deserialized it will be considered [`None`][]. +/// +/// Deserialized documents are compared like `Some(doc0).cmp(&Some(doc1))`, +/// so you must check the [`Ord`] of `Option` implementation. +/// +/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None +/// [`Ord`]: https://doc.rust-lang.org/std/option/enum.Option.html#impl-Ord +/// +/// # Example +/// +/// ```no-test +/// use serde_derive::Deserialize; +/// use meilidb::rank::criterion::*; +/// +/// #[derive(Deserialize, PartialOrd, Ord, PartialEq, Eq)] +/// struct TimeOnly { +/// time: String, +/// } +/// +/// let builder = CriteriaBuilder::with_capacity(8) +/// .add(SumOfTypos) +/// .add(NumberOfWords) +/// .add(WordsProximity) +/// .add(SumOfWordsAttribute) +/// .add(SumOfWordsPosition) +/// .add(Exact) +/// .add(SortBy::::new()) +/// .add(DocumentId); +/// +/// let criterion = builder.build(); +/// +/// ``` +#[derive(Default)] +pub struct SortBy { + _phantom: marker::PhantomData, +} + +impl SortBy { + pub fn new() -> Self { + SortBy { _phantom: marker::PhantomData } + } +} + +impl Criterion for SortBy +where D: Deref, + T: DeserializeOwned + Ord, +{ + fn evaluate(&self, lhs: &Document, rhs: &Document, view: &DatabaseView) -> Ordering { + let lhs = match view.retrieve_document::(lhs.id) { + Ok(doc) => Some(doc), + Err(e) => { eprintln!("{}", e); None }, + }; + + let rhs = match view.retrieve_document::(rhs.id) { + Ok(doc) => Some(doc), + Err(e) => { eprintln!("{}", e); None }, + }; + + lhs.cmp(&rhs) + } +}