mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-30 00:34:26 +01:00
feat: Introduce the Number type
This commit is contained in:
parent
83cd071827
commit
db6210c7ee
@ -8,13 +8,13 @@ use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crossbeam::atomic::ArcCell;
|
||||
use log::{info, error, warn};
|
||||
use rocksdb::rocksdb::{Writable, Snapshot};
|
||||
use rocksdb::rocksdb_options::{DBOptions, ColumnFamilyOptions};
|
||||
use rocksdb::rocksdb::{Writable, Snapshot};
|
||||
use rocksdb::{DB, MergeOperands};
|
||||
use crossbeam::atomic::ArcCell;
|
||||
use lockfree::map::Map;
|
||||
use hashbrown::HashMap;
|
||||
use log::{info, error, warn};
|
||||
|
||||
pub use self::document_key::{DocumentKey, DocumentKeyAttr};
|
||||
pub use self::view::{DatabaseView, DocumentIter};
|
||||
@ -22,8 +22,9 @@ pub use self::update::Update;
|
||||
pub use self::serde::SerializerError;
|
||||
pub use self::schema::Schema;
|
||||
pub use self::index::Index;
|
||||
pub use self::number::{Number, ParseNumberError};
|
||||
|
||||
pub type RankedMap = HashMap<(DocumentId, SchemaAttr), i64>;
|
||||
pub type RankedMap = HashMap<(DocumentId, SchemaAttr), Number>;
|
||||
|
||||
const DATA_INDEX: &[u8] = b"data-index";
|
||||
const DATA_RANKED_MAP: &[u8] = b"data-ranked-map";
|
||||
@ -31,6 +32,7 @@ const DATA_SCHEMA: &[u8] = b"data-schema";
|
||||
|
||||
pub mod schema;
|
||||
pub(crate) mod index;
|
||||
mod number;
|
||||
mod document_key;
|
||||
mod serde;
|
||||
mod update;
|
||||
|
98
src/database/number.rs
Normal file
98
src/database/number.rs
Normal file
@ -0,0 +1,98 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::str::FromStr;
|
||||
use std::fmt;
|
||||
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Number {
|
||||
Unsigned(u64),
|
||||
Signed(i64),
|
||||
Float(f64),
|
||||
}
|
||||
|
||||
impl FromStr for Number {
|
||||
type Err = ParseNumberError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if let Ok(unsigned) = u64::from_str(s) {
|
||||
return Ok(Number::Unsigned(unsigned))
|
||||
}
|
||||
|
||||
if let Ok(signed) = i64::from_str(s) {
|
||||
return Ok(Number::Signed(signed))
|
||||
}
|
||||
|
||||
if let Ok(float) = f64::from_str(s) {
|
||||
if float == 0.0 || float.is_normal() {
|
||||
return Ok(Number::Float(float))
|
||||
}
|
||||
}
|
||||
|
||||
Err(ParseNumberError)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Number {
|
||||
fn partial_cmp(&self, other: &Number) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Number {
|
||||
fn cmp(&self, other: &Number) -> Ordering {
|
||||
use Number::*;
|
||||
match (self, other) {
|
||||
(Unsigned(s), Unsigned(o)) => s.cmp(o),
|
||||
(Unsigned(s), Signed(o)) => {
|
||||
let s = i128::from(*s);
|
||||
let o = i128::from(*o);
|
||||
s.cmp(&o)
|
||||
},
|
||||
(Unsigned(s), Float(o)) => {
|
||||
let s = *s as f64;
|
||||
s.partial_cmp(&o).unwrap_or(Ordering::Equal)
|
||||
},
|
||||
|
||||
(Signed(s), Unsigned(o)) => {
|
||||
let s = i128::from(*s);
|
||||
let o = i128::from(*o);
|
||||
s.cmp(&o)
|
||||
},
|
||||
(Signed(s), Signed(o)) => s.cmp(o),
|
||||
(Signed(s), Float(o)) => {
|
||||
let s = *s as f64;
|
||||
s.partial_cmp(o).unwrap_or(Ordering::Equal)
|
||||
},
|
||||
|
||||
(Float(s), Unsigned(o)) => {
|
||||
let o = *o as f64;
|
||||
s.partial_cmp(&o).unwrap_or(Ordering::Equal)
|
||||
},
|
||||
(Float(s), Signed(o)) => {
|
||||
let o = *o as f64;
|
||||
s.partial_cmp(&o).unwrap_or(Ordering::Equal)
|
||||
},
|
||||
(Float(s), Float(o)) => {
|
||||
s.partial_cmp(o).unwrap_or(Ordering::Equal)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Number {
|
||||
fn eq(&self, other: &Number) -> bool {
|
||||
self.cmp(other) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Number { }
|
||||
|
||||
pub struct ParseNumberError;
|
||||
|
||||
impl fmt::Display for ParseNumberError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str("can not parse number")
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ macro_rules! forward_to_unserializable_type {
|
||||
|
||||
pub mod find_id;
|
||||
pub mod key_to_string;
|
||||
pub mod value_to_i64;
|
||||
pub mod value_to_number;
|
||||
pub mod serializer;
|
||||
pub mod indexer_serializer;
|
||||
pub mod deserializer;
|
||||
|
@ -5,7 +5,7 @@ use serde::ser;
|
||||
|
||||
use crate::database::serde::indexer_serializer::IndexerSerializer;
|
||||
use crate::database::serde::key_to_string::KeyToStringSerializer;
|
||||
use crate::database::serde::value_to_i64::ValueToI64Serializer;
|
||||
use crate::database::serde::value_to_number::ValueToNumberSerializer;
|
||||
use crate::database::update::DocumentUpdate;
|
||||
use crate::database::serde::SerializerError;
|
||||
use crate::tokenizer::TokenizerBuilder;
|
||||
@ -231,8 +231,8 @@ where B: TokenizerBuilder
|
||||
value.serialize(serializer)?;
|
||||
}
|
||||
if props.is_ranked() {
|
||||
let integer = value.serialize(ValueToI64Serializer)?;
|
||||
self.update.register_ranked_attribute(attr, integer)?;
|
||||
let number = value.serialize(ValueToNumberSerializer)?;
|
||||
self.update.register_ranked_attribute(attr, number)?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ where B: TokenizerBuilder
|
||||
value.serialize(serializer)?;
|
||||
}
|
||||
if props.is_ranked() {
|
||||
let integer = value.serialize(ValueToI64Serializer)?;
|
||||
let integer = value.serialize(ValueToNumberSerializer)?;
|
||||
self.update.register_ranked_attribute(attr, integer)?;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::{ser, ser::Error};
|
||||
|
||||
use crate::database::serde::SerializerError;
|
||||
use crate::database::Number;
|
||||
|
||||
pub struct ValueToI64Serializer;
|
||||
pub struct ValueToNumberSerializer;
|
||||
|
||||
impl ser::Serializer for ValueToI64Serializer {
|
||||
type Ok = i64;
|
||||
impl ser::Serializer for ValueToNumberSerializer {
|
||||
type Ok = Number;
|
||||
type Error = SerializerError;
|
||||
type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
|
||||
type SerializeTuple = ser::Impossible<Self::Ok, Self::Error>;
|
||||
@ -19,46 +22,50 @@ impl ser::Serializer for ValueToI64Serializer {
|
||||
forward_to_unserializable_type! {
|
||||
bool => serialize_bool,
|
||||
char => serialize_char,
|
||||
|
||||
f32 => serialize_f32,
|
||||
f64 => serialize_f64,
|
||||
}
|
||||
|
||||
fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(i64::from(value))
|
||||
Ok(Number::Signed(value as i64))
|
||||
}
|
||||
|
||||
fn serialize_i16(self, value: i16) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(i64::from(value))
|
||||
Ok(Number::Signed(value as i64))
|
||||
}
|
||||
|
||||
fn serialize_i32(self, value: i32) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(i64::from(value))
|
||||
Ok(Number::Signed(value as i64))
|
||||
}
|
||||
|
||||
fn serialize_i64(self, value: i64) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(i64::from(value))
|
||||
Ok(Number::Signed(value as i64))
|
||||
}
|
||||
|
||||
fn serialize_u8(self, value: u8) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(i64::from(value))
|
||||
Ok(Number::Unsigned(value as u64))
|
||||
}
|
||||
|
||||
fn serialize_u16(self, value: u16) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(i64::from(value))
|
||||
Ok(Number::Unsigned(value as u64))
|
||||
}
|
||||
|
||||
fn serialize_u32(self, value: u32) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(i64::from(value))
|
||||
Ok(Number::Unsigned(value as u64))
|
||||
}
|
||||
|
||||
fn serialize_u64(self, value: u64) -> Result<Self::Ok, Self::Error> {
|
||||
// Ok(i64::from(value))
|
||||
unimplemented!()
|
||||
Ok(Number::Unsigned(value as u64))
|
||||
}
|
||||
|
||||
fn serialize_f32(self, value: f32) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(Number::Float(value as f64))
|
||||
}
|
||||
|
||||
fn serialize_f64(self, value: f64) -> Result<Self::Ok, Self::Error> {
|
||||
Ok(Number::Float(value))
|
||||
}
|
||||
|
||||
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
|
||||
i64::from_str_radix(value, 10).map_err(SerializerError::custom)
|
||||
Number::from_str(value).map_err(SerializerError::custom)
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
|
@ -16,8 +16,8 @@ use crate::tokenizer::TokenizerBuilder;
|
||||
use crate::data::{DocIds, DocIndexes};
|
||||
use crate::database::schema::Schema;
|
||||
use crate::database::index::Index;
|
||||
use crate::database::RankedMap;
|
||||
use crate::database::{DATA_INDEX, DATA_RANKED_MAP};
|
||||
use crate::database::{RankedMap, Number};
|
||||
use crate::{DocumentId, DocIndex};
|
||||
|
||||
pub type Token = Vec<u8>; // TODO could be replaced by a SmallVec
|
||||
@ -205,7 +205,7 @@ impl<'a> DocumentUpdate<'a> {
|
||||
pub fn register_ranked_attribute(
|
||||
&mut self,
|
||||
attr: SchemaAttr,
|
||||
integer: i64,
|
||||
number: Number,
|
||||
) -> Result<(), SerializerError>
|
||||
{
|
||||
use serde::ser::Error;
|
||||
@ -216,7 +216,7 @@ impl<'a> DocumentUpdate<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
self.inner.documents_ranked_fields.insert((self.document_id, attr), integer);
|
||||
self.inner.documents_ranked_fields.insert((self.document_id, attr), number);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ use crate::database::{retrieve_data_schema, retrieve_data_index, retrieve_data_r
|
||||
use crate::database::serde::deserializer::Deserializer;
|
||||
use crate::database::{DocumentKey, DocumentKeyAttr};
|
||||
use crate::rank::{QueryBuilder, FilterFunc};
|
||||
use crate::database::schema::SchemaAttr;
|
||||
use crate::database::schema::Schema;
|
||||
use crate::database::index::Index;
|
||||
use crate::database::RankedMap;
|
||||
|
Loading…
Reference in New Issue
Block a user