2018-05-05 10:59:03 +02:00
|
|
|
#[macro_use] extern crate serde_derive;
|
2018-04-22 17:34:41 +02:00
|
|
|
extern crate bincode;
|
2018-04-22 15:54:34 +02:00
|
|
|
extern crate fst;
|
2018-05-27 15:23:43 +02:00
|
|
|
extern crate group_by;
|
2018-05-13 12:38:24 +02:00
|
|
|
extern crate levenshtein_automata;
|
2018-05-05 10:59:03 +02:00
|
|
|
extern crate serde;
|
2018-04-22 15:54:34 +02:00
|
|
|
|
2018-05-12 13:28:43 +02:00
|
|
|
pub mod map;
|
2018-05-27 15:23:43 +02:00
|
|
|
pub mod rank;
|
2018-05-13 12:38:24 +02:00
|
|
|
mod levenshtein;
|
2018-04-22 15:54:34 +02:00
|
|
|
|
2018-06-24 15:10:13 +02:00
|
|
|
use std::path::Path;
|
|
|
|
use std::fs;
|
|
|
|
|
2018-05-12 13:22:07 +02:00
|
|
|
pub use self::map::{Map, MapBuilder, Values};
|
|
|
|
pub use self::map::{
|
2018-05-06 12:23:42 +02:00
|
|
|
OpBuilder, IndexedValues,
|
|
|
|
OpWithStateBuilder, IndexedValuesWithState,
|
|
|
|
};
|
2018-05-27 15:23:43 +02:00
|
|
|
pub use self::rank::{RankedStream};
|
2018-05-13 12:38:24 +02:00
|
|
|
pub use self::levenshtein::LevBuilder;
|
2018-05-13 15:12:15 +02:00
|
|
|
|
2018-05-27 11:15:05 +02:00
|
|
|
pub type DocIndexMap = Map<DocIndex>;
|
|
|
|
pub type DocIndexMapBuilder = MapBuilder<DocIndex>;
|
|
|
|
|
2018-05-27 15:23:43 +02:00
|
|
|
pub type DocumentId = u64;
|
|
|
|
|
2018-05-27 11:15:05 +02:00
|
|
|
/// This structure represent the position of a word
|
|
|
|
/// in a document and its attributes.
|
|
|
|
///
|
|
|
|
/// This is stored in the map, generated at index time,
|
|
|
|
/// extracted and interpreted at search time.
|
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
|
|
pub struct DocIndex {
|
|
|
|
|
|
|
|
/// The document identifier where the word was found.
|
2018-05-27 15:23:43 +02:00
|
|
|
pub document: DocumentId,
|
2018-05-27 11:15:05 +02:00
|
|
|
|
|
|
|
/// The attribute identifier in the document
|
|
|
|
/// where the word was found.
|
|
|
|
///
|
|
|
|
/// This is an `u8` therefore a document
|
|
|
|
/// can not have more than `2^8` attributes.
|
|
|
|
pub attribute: u8,
|
|
|
|
|
|
|
|
/// The index where the word was found in the attribute.
|
|
|
|
///
|
|
|
|
/// Only the first 1000 words are indexed.
|
|
|
|
pub attribute_index: u32,
|
2018-05-13 15:12:15 +02:00
|
|
|
}
|
|
|
|
|
2018-05-27 11:15:05 +02:00
|
|
|
/// This structure represent a matching word with informations
|
|
|
|
/// on the location of the word in the document.
|
|
|
|
///
|
|
|
|
/// The order of the field is important because it defines
|
|
|
|
/// the way these structures are ordered between themselves.
|
|
|
|
///
|
|
|
|
/// The word in itself is not important.
|
2018-05-27 15:23:43 +02:00
|
|
|
// TODO do data oriented programming ? very arrays ?
|
2018-05-27 11:15:05 +02:00
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
|
|
|
pub struct Match {
|
|
|
|
|
2018-05-27 15:23:43 +02:00
|
|
|
/// The word index in the query sentence.
|
|
|
|
/// Same as the `attribute_index` but for the query words.
|
|
|
|
///
|
|
|
|
/// Used to retrieve the automaton that match this word.
|
|
|
|
pub query_index: u32,
|
|
|
|
|
2018-05-27 11:15:05 +02:00
|
|
|
/// The distance the word has with the query word
|
|
|
|
/// (i.e. the Levenshtein distance).
|
|
|
|
pub distance: u8,
|
|
|
|
|
|
|
|
/// The attribute in which the word is located
|
|
|
|
/// (i.e. Title is 0, Description is 1).
|
|
|
|
///
|
|
|
|
/// This is an `u8` therefore a document
|
|
|
|
/// can not have more than `2^8` attributes.
|
2018-05-13 15:12:15 +02:00
|
|
|
pub attribute: u8,
|
2018-05-27 11:15:05 +02:00
|
|
|
|
|
|
|
/// Where does this word is located in the attribute string
|
|
|
|
/// (i.e. at the start or the end of the attribute).
|
|
|
|
///
|
|
|
|
/// The index in the attribute is limited to a maximum of `2^32`
|
|
|
|
/// this is because we index only the first 1000 words in an attribute.
|
|
|
|
pub attribute_index: u32,
|
2018-05-13 15:12:15 +02:00
|
|
|
}
|
2018-05-27 15:23:43 +02:00
|
|
|
|
|
|
|
impl Match {
|
|
|
|
pub fn zero() -> Self {
|
|
|
|
Match {
|
|
|
|
query_index: 0,
|
|
|
|
distance: 0,
|
|
|
|
attribute: 0,
|
|
|
|
attribute_index: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn max() -> Self {
|
|
|
|
Match {
|
|
|
|
query_index: u32::max_value(),
|
|
|
|
distance: u8::max_value(),
|
|
|
|
attribute: u8::max_value(),
|
|
|
|
attribute_index: u32::max_value(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-06-24 15:10:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
pub fn load_map<P, Q>(map: P, values: Q) -> fst::Result<DocIndexMap>
|
|
|
|
where P: AsRef<Path>, Q: AsRef<Path>,
|
|
|
|
{
|
|
|
|
let fst = fs::read(map)?;
|
|
|
|
let values = fs::read(values)?;
|
|
|
|
DocIndexMap::from_bytes(fst, &values)
|
|
|
|
}
|