mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-26 23:04: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::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::ops::{Deref, DerefMut};
|
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_options::{DBOptions, ColumnFamilyOptions};
|
||||||
|
use rocksdb::rocksdb::{Writable, Snapshot};
|
||||||
use rocksdb::{DB, MergeOperands};
|
use rocksdb::{DB, MergeOperands};
|
||||||
|
use crossbeam::atomic::ArcCell;
|
||||||
use lockfree::map::Map;
|
use lockfree::map::Map;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use log::{info, error, warn};
|
||||||
|
|
||||||
pub use self::document_key::{DocumentKey, DocumentKeyAttr};
|
pub use self::document_key::{DocumentKey, DocumentKeyAttr};
|
||||||
pub use self::view::{DatabaseView, DocumentIter};
|
pub use self::view::{DatabaseView, DocumentIter};
|
||||||
@ -22,8 +22,9 @@ pub use self::update::Update;
|
|||||||
pub use self::serde::SerializerError;
|
pub use self::serde::SerializerError;
|
||||||
pub use self::schema::Schema;
|
pub use self::schema::Schema;
|
||||||
pub use self::index::Index;
|
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_INDEX: &[u8] = b"data-index";
|
||||||
const DATA_RANKED_MAP: &[u8] = b"data-ranked-map";
|
const DATA_RANKED_MAP: &[u8] = b"data-ranked-map";
|
||||||
@ -31,6 +32,7 @@ const DATA_SCHEMA: &[u8] = b"data-schema";
|
|||||||
|
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub(crate) mod index;
|
pub(crate) mod index;
|
||||||
|
mod number;
|
||||||
mod document_key;
|
mod document_key;
|
||||||
mod serde;
|
mod serde;
|
||||||
mod update;
|
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 find_id;
|
||||||
pub mod key_to_string;
|
pub mod key_to_string;
|
||||||
pub mod value_to_i64;
|
pub mod value_to_number;
|
||||||
pub mod serializer;
|
pub mod serializer;
|
||||||
pub mod indexer_serializer;
|
pub mod indexer_serializer;
|
||||||
pub mod deserializer;
|
pub mod deserializer;
|
||||||
|
@ -5,7 +5,7 @@ use serde::ser;
|
|||||||
|
|
||||||
use crate::database::serde::indexer_serializer::IndexerSerializer;
|
use crate::database::serde::indexer_serializer::IndexerSerializer;
|
||||||
use crate::database::serde::key_to_string::KeyToStringSerializer;
|
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::update::DocumentUpdate;
|
||||||
use crate::database::serde::SerializerError;
|
use crate::database::serde::SerializerError;
|
||||||
use crate::tokenizer::TokenizerBuilder;
|
use crate::tokenizer::TokenizerBuilder;
|
||||||
@ -231,8 +231,8 @@ where B: TokenizerBuilder
|
|||||||
value.serialize(serializer)?;
|
value.serialize(serializer)?;
|
||||||
}
|
}
|
||||||
if props.is_ranked() {
|
if props.is_ranked() {
|
||||||
let integer = value.serialize(ValueToI64Serializer)?;
|
let number = value.serialize(ValueToNumberSerializer)?;
|
||||||
self.update.register_ranked_attribute(attr, integer)?;
|
self.update.register_ranked_attribute(attr, number)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,7 +282,7 @@ where B: TokenizerBuilder
|
|||||||
value.serialize(serializer)?;
|
value.serialize(serializer)?;
|
||||||
}
|
}
|
||||||
if props.is_ranked() {
|
if props.is_ranked() {
|
||||||
let integer = value.serialize(ValueToI64Serializer)?;
|
let integer = value.serialize(ValueToNumberSerializer)?;
|
||||||
self.update.register_ranked_attribute(attr, integer)?;
|
self.update.register_ranked_attribute(attr, integer)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::{ser, ser::Error};
|
use serde::{ser, ser::Error};
|
||||||
|
|
||||||
use crate::database::serde::SerializerError;
|
use crate::database::serde::SerializerError;
|
||||||
|
use crate::database::Number;
|
||||||
|
|
||||||
pub struct ValueToI64Serializer;
|
pub struct ValueToNumberSerializer;
|
||||||
|
|
||||||
impl ser::Serializer for ValueToI64Serializer {
|
impl ser::Serializer for ValueToNumberSerializer {
|
||||||
type Ok = i64;
|
type Ok = Number;
|
||||||
type Error = SerializerError;
|
type Error = SerializerError;
|
||||||
type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
|
type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
|
||||||
type SerializeTuple = 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! {
|
forward_to_unserializable_type! {
|
||||||
bool => serialize_bool,
|
bool => serialize_bool,
|
||||||
char => serialize_char,
|
char => serialize_char,
|
||||||
|
|
||||||
f32 => serialize_f32,
|
|
||||||
f64 => serialize_f64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
|
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> {
|
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> {
|
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> {
|
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> {
|
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> {
|
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> {
|
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> {
|
fn serialize_u64(self, value: u64) -> Result<Self::Ok, Self::Error> {
|
||||||
// Ok(i64::from(value))
|
Ok(Number::Unsigned(value as u64))
|
||||||
unimplemented!()
|
}
|
||||||
|
|
||||||
|
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> {
|
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> {
|
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::data::{DocIds, DocIndexes};
|
||||||
use crate::database::schema::Schema;
|
use crate::database::schema::Schema;
|
||||||
use crate::database::index::Index;
|
use crate::database::index::Index;
|
||||||
use crate::database::RankedMap;
|
|
||||||
use crate::database::{DATA_INDEX, DATA_RANKED_MAP};
|
use crate::database::{DATA_INDEX, DATA_RANKED_MAP};
|
||||||
|
use crate::database::{RankedMap, Number};
|
||||||
use crate::{DocumentId, DocIndex};
|
use crate::{DocumentId, DocIndex};
|
||||||
|
|
||||||
pub type Token = Vec<u8>; // TODO could be replaced by a SmallVec
|
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(
|
pub fn register_ranked_attribute(
|
||||||
&mut self,
|
&mut self,
|
||||||
attr: SchemaAttr,
|
attr: SchemaAttr,
|
||||||
integer: i64,
|
number: Number,
|
||||||
) -> Result<(), SerializerError>
|
) -> Result<(), SerializerError>
|
||||||
{
|
{
|
||||||
use serde::ser::Error;
|
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(())
|
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::serde::deserializer::Deserializer;
|
||||||
use crate::database::{DocumentKey, DocumentKeyAttr};
|
use crate::database::{DocumentKey, DocumentKeyAttr};
|
||||||
use crate::rank::{QueryBuilder, FilterFunc};
|
use crate::rank::{QueryBuilder, FilterFunc};
|
||||||
use crate::database::schema::SchemaAttr;
|
|
||||||
use crate::database::schema::Schema;
|
use crate::database::schema::Schema;
|
||||||
use crate::database::index::Index;
|
use crate::database::index::Index;
|
||||||
use crate::database::RankedMap;
|
use crate::database::RankedMap;
|
||||||
|
Loading…
Reference in New Issue
Block a user