fixes for review

This commit is contained in:
qdequele 2020-02-11 15:16:02 +01:00
parent 40d7396d90
commit dc9ca2ebc9
No known key found for this signature in database
GPG Key ID: B3F0A000EBF11745
20 changed files with 66 additions and 64 deletions

View File

@ -1,7 +1,7 @@
{ {
"identifier": "id", "identifier": "id",
"searchable_attributes": ["title", "overview"], "searchableAttributes": ["title", "overview"],
"displayed_attributes": [ "displayedAttributes": [
"id", "id",
"title", "title",
"overview", "overview",

View File

@ -172,7 +172,6 @@ where
debug!("bucket sort took {:.02?}", before_bucket_sort.elapsed()); debug!("bucket sort took {:.02?}", before_bucket_sort.elapsed());
Ok(documents) Ok(documents)
} }

View File

@ -87,12 +87,12 @@ impl fmt::Display for Error {
match self { match self {
Io(e) => write!(f, "{}", e), Io(e) => write!(f, "{}", e),
IndexAlreadyExists => write!(f, "index already exists"), IndexAlreadyExists => write!(f, "index already exists"),
MissingIdentifier => write!(f, "schema cannot be build without identifier"), MissingIdentifier => write!(f, "schema cannot be built without identifier"),
SchemaMissing => write!(f, "this index does not have a schema"), SchemaMissing => write!(f, "this index does not have a schema"),
WordIndexMissing => write!(f, "this index does not have a word index"), WordIndexMissing => write!(f, "this index does not have a word index"),
MissingDocumentId => write!(f, "document id is missing"), MissingDocumentId => write!(f, "document id is missing"),
MaxFieldsLimitExceeded => write!(f, "maximum field in a document is exceeded"), MaxFieldsLimitExceeded => write!(f, "maximum number of fields in a document exceeded"),
Schema(e) => write!(f, "schemas error; {}", e), Schema(e) => write!(f, "schema error; {}", e),
Zlmdb(e) => write!(f, "heed error; {}", e), Zlmdb(e) => write!(f, "heed error; {}", e),
Fst(e) => write!(f, "fst error; {}", e), Fst(e) => write!(f, "fst error; {}", e),
SerdeJson(e) => write!(f, "serde json error; {}", e), SerdeJson(e) => write!(f, "serde json error; {}", e),

View File

@ -275,7 +275,7 @@ mod tests {
let mut final_indexes = Vec::new(); let mut final_indexes = Vec::new();
for index in indexes { for index in indexes {
let name = index.attribute.to_string(); let name = index.attribute.to_string();
schema.get_or_create_empty(&name).unwrap(); schema.insert(&name).unwrap();
let indexed_pos = schema.set_indexed(&name).unwrap().1; let indexed_pos = schema.set_indexed(&name).unwrap().1;
let index = DocIndex { let index = DocIndex {
attribute: indexed_pos.0, attribute: indexed_pos.0,

View File

@ -235,7 +235,7 @@ impl<'a, 'b> ser::SerializeMap for MapSerializer<'a, 'b> {
let key = key.serialize(ConvertToString)?; let key = key.serialize(ConvertToString)?;
serialize_value( serialize_value(
self.txn, self.txn,
key, key.as_str(),
self.schema, self.schema,
self.document_id, self.document_id,
self.document_store, self.document_store,
@ -275,7 +275,7 @@ impl<'a, 'b> ser::SerializeStruct for StructSerializer<'a, 'b> {
{ {
serialize_value( serialize_value(
self.txn, self.txn,
key.to_string(), key,
self.schema, self.schema,
self.document_id, self.document_id,
self.document_store, self.document_store,
@ -293,7 +293,7 @@ impl<'a, 'b> ser::SerializeStruct for StructSerializer<'a, 'b> {
pub fn serialize_value<'a, T: ?Sized>( pub fn serialize_value<'a, T: ?Sized>(
txn: &mut heed::RwTxn<MainT>, txn: &mut heed::RwTxn<MainT>,
attribute: String, attribute: &str,
schema: &'a mut Schema, schema: &'a mut Schema,
document_id: DocumentId, document_id: DocumentId,
document_store: DocumentsFields, document_store: DocumentsFields,
@ -305,7 +305,7 @@ pub fn serialize_value<'a, T: ?Sized>(
where where
T: ser::Serialize, T: ser::Serialize,
{ {
let field_id = schema.get_or_create(&attribute)?; let field_id = schema.insert_and_index(&attribute)?;
serialize_value_with_id( serialize_value_with_id(
txn, txn,
field_id, field_id,

View File

@ -1,5 +1,6 @@
use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::str::FromStr; use std::str::FromStr;
use std::iter::IntoIterator;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -17,8 +18,6 @@ pub struct Settings {
#[serde(default, deserialize_with = "deserialize_some")] #[serde(default, deserialize_with = "deserialize_some")]
pub ranking_distinct: Option<Option<String>>, pub ranking_distinct: Option<Option<String>>,
#[serde(default, deserialize_with = "deserialize_some")] #[serde(default, deserialize_with = "deserialize_some")]
pub identifier: Option<Option<String>>,
#[serde(default, deserialize_with = "deserialize_some")]
pub searchable_attributes: Option<Option<Vec<String>>>, pub searchable_attributes: Option<Option<Vec<String>>>,
#[serde(default, deserialize_with = "deserialize_some")] #[serde(default, deserialize_with = "deserialize_some")]
pub displayed_attributes: Option<Option<HashSet<String>>>, pub displayed_attributes: Option<Option<HashSet<String>>>,
@ -43,7 +42,7 @@ impl Settings {
let settings = self.clone(); let settings = self.clone();
let ranking_rules = match settings.ranking_rules { let ranking_rules = match settings.ranking_rules {
Some(Some(rules)) => UpdateState::Update(RankingRule::from_vec(rules.iter().map(|m| m.as_ref()).collect())?), Some(Some(rules)) => UpdateState::Update(RankingRule::from_iter(rules.iter())?),
Some(None) => UpdateState::Clear, Some(None) => UpdateState::Clear,
None => UpdateState::Nothing, None => UpdateState::Nothing,
}; };
@ -51,7 +50,7 @@ impl Settings {
Ok(SettingsUpdate { Ok(SettingsUpdate {
ranking_rules, ranking_rules,
ranking_distinct: settings.ranking_distinct.into(), ranking_distinct: settings.ranking_distinct.into(),
identifier: settings.identifier.into(), identifier: UpdateState::Nothing,
searchable_attributes: settings.searchable_attributes.into(), searchable_attributes: settings.searchable_attributes.into(),
displayed_attributes: settings.displayed_attributes.into(), displayed_attributes: settings.displayed_attributes.into(),
stop_words: settings.stop_words.into(), stop_words: settings.stop_words.into(),
@ -139,16 +138,16 @@ impl FromStr for RankingRule {
} }
impl RankingRule { impl RankingRule {
pub fn get_field(&self) -> Option<&str> { pub fn field(&self) -> Option<&str> {
match self { match self {
RankingRule::Asc(field) | RankingRule::Dsc(field) => Some(field), RankingRule::Asc(field) | RankingRule::Dsc(field) => Some(field),
_ => None, _ => None,
} }
} }
pub fn from_vec(rules: Vec<&str>) -> Result<Vec<RankingRule>, RankingRuleConversionError> { pub fn from_iter(rules: impl IntoIterator<Item = impl AsRef<str>>) -> Result<Vec<RankingRule>, RankingRuleConversionError> {
rules.iter() rules.into_iter()
.map(|s| RankingRule::from_str(s)) .map(|s| RankingRule::from_str(s.as_ref()))
.collect() .collect()
} }
} }

View File

@ -192,8 +192,8 @@ impl Main {
self.main.get::<_, Str, SerdeBincode<Vec<RankingRule>>>(reader, RANKING_RULES_KEY) self.main.get::<_, Str, SerdeBincode<Vec<RankingRule>>>(reader, RANKING_RULES_KEY)
} }
pub fn put_ranking_rules(self, writer: &mut heed::RwTxn<MainT>, value: Vec<RankingRule>) -> ZResult<()> { pub fn put_ranking_rules(self, writer: &mut heed::RwTxn<MainT>, value: &[RankingRule]) -> ZResult<()> {
self.main.put::<_, Str, SerdeBincode<Vec<RankingRule>>>(writer, RANKING_RULES_KEY, &value) self.main.put::<_, Str, SerdeBincode<Vec<RankingRule>>>(writer, RANKING_RULES_KEY, &value.to_vec())
} }
pub fn delete_ranking_rules(self, writer: &mut heed::RwTxn<MainT>) -> ZResult<bool> { pub fn delete_ranking_rules(self, writer: &mut heed::RwTxn<MainT>) -> ZResult<bool> {
@ -201,11 +201,14 @@ impl Main {
} }
pub fn ranking_distinct(&self, reader: &heed::RoTxn<MainT>) -> ZResult<Option<String>> { pub fn ranking_distinct(&self, reader: &heed::RoTxn<MainT>) -> ZResult<Option<String>> {
self.main.get::<_, Str, SerdeBincode<String>>(reader, RANKING_DISTINCT_KEY) if let Some(value) = self.main.get::<_, Str, Str>(reader, RANKING_DISTINCT_KEY)? {
return Ok(Some(value.to_owned()))
}
return Ok(None)
} }
pub fn put_ranking_distinct(self, writer: &mut heed::RwTxn<MainT>, value: String) -> ZResult<()> { pub fn put_ranking_distinct(self, writer: &mut heed::RwTxn<MainT>, value: &str) -> ZResult<()> {
self.main.put::<_, Str, SerdeBincode<String>>(writer, RANKING_DISTINCT_KEY, &value) self.main.put::<_, Str, Str>(writer, RANKING_DISTINCT_KEY, value)
} }
pub fn delete_ranking_distinct(self, writer: &mut heed::RwTxn<MainT>) -> ZResult<bool> { pub fn delete_ranking_distinct(self, writer: &mut heed::RwTxn<MainT>) -> ZResult<bool> {

View File

@ -106,7 +106,7 @@ pub fn apply_documents_deletion(
let mut words_document_ids = HashMap::new(); let mut words_document_ids = HashMap::new();
for id in idset { for id in idset {
// remove all the ranked attributes from the ranked_map // remove all the ranked attributes from the ranked_map
for ranked_attr in &ranked_fields { for ranked_attr in ranked_fields {
ranked_map.remove(id, *ranked_attr); ranked_map.remove(id, *ranked_attr);
} }

View File

@ -44,9 +44,9 @@ pub fn apply_settings_update(
match settings.ranking_rules { match settings.ranking_rules {
UpdateState::Update(v) => { UpdateState::Update(v) => {
let ranked_field: Vec<&str> = v.iter().filter_map(RankingRule::get_field).collect(); let ranked_field: Vec<&str> = v.iter().filter_map(RankingRule::field).collect();
schema.update_ranked(ranked_field)?; schema.update_ranked(ranked_field)?;
index.main.put_ranking_rules(writer, v)?; index.main.put_ranking_rules(writer, &v)?;
must_reindex = true; must_reindex = true;
}, },
UpdateState::Clear => { UpdateState::Clear => {
@ -60,7 +60,7 @@ pub fn apply_settings_update(
match settings.ranking_distinct { match settings.ranking_distinct {
UpdateState::Update(v) => { UpdateState::Update(v) => {
index.main.put_ranking_distinct(writer, v)?; index.main.put_ranking_distinct(writer, &v)?;
}, },
UpdateState::Clear => { UpdateState::Clear => {
index.main.delete_ranking_distinct(writer)?; index.main.delete_ranking_distinct(writer)?;
@ -99,16 +99,12 @@ pub fn apply_settings_update(
UpdateState::Nothing => (), UpdateState::Nothing => (),
}; };
match settings.identifier.clone() { if let UpdateState::Update(v) = settings.identifier.clone() {
UpdateState::Update(v) => { schema.set_identifier(v.as_ref())?;
schema.set_identifier(v.as_ref())?; must_reindex = true;
index.main.put_schema(writer, &schema)?; }
must_reindex = true;
}, index.main.put_schema(writer, &schema)?;
_ => {
index.main.put_schema(writer, &schema)?;
},
};
match settings.stop_words { match settings.stop_words {
UpdateState::Update(stop_words) => { UpdateState::Update(stop_words) => {
@ -121,13 +117,13 @@ pub fn apply_settings_update(
must_reindex = true; must_reindex = true;
} }
}, },
_ => (), UpdateState::Nothing => (),
} }
match settings.synonyms { match settings.synonyms {
UpdateState::Update(synonyms) => apply_synonyms_update(writer, index, synonyms)?, UpdateState::Update(synonyms) => apply_synonyms_update(writer, index, synonyms)?,
UpdateState::Clear => apply_synonyms_update(writer, index, BTreeMap::new())?, UpdateState::Clear => apply_synonyms_update(writer, index, BTreeMap::new())?,
_ => (), UpdateState::Nothing => (),
} }
if must_reindex { if must_reindex {

Binary file not shown.

View File

@ -92,7 +92,13 @@ impl DataInner {
// convert attributes to their names // convert attributes to their names
let frequency: HashMap<_, _> = fields_frequency let frequency: HashMap<_, _> = fields_frequency
.into_iter() .into_iter()
.map(|(a, c)| (schema.name(a).unwrap().to_string(), c)) .filter_map(|(a, c)| {
if let Some(name) = schema.name(a) {
return Some((name.to_string(), c));
} else {
return None;
}
})
.collect(); .collect();
index index

View File

@ -2,10 +2,10 @@ use std::fmt::Display;
use http::status::StatusCode; use http::status::StatusCode;
use log::{error, warn}; use log::{error, warn};
use meilisearch_core::{FstError, HeedError};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tide::IntoResponse; use tide::IntoResponse;
use tide::Response; use tide::Response;
use meilisearch_core::{HeedError, FstError};
use crate::helpers::meilisearch::Error as SearchError; use crate::helpers::meilisearch::Error as SearchError;

View File

@ -206,7 +206,8 @@ impl<'a> SearchBuilder<'a> {
query_builder.with_fetch_timeout(self.timeout); query_builder.with_fetch_timeout(self.timeout);
let start = Instant::now(); let start = Instant::now();
let docs = query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit)); let docs =
query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit));
let time_ms = start.elapsed().as_millis() as usize; let time_ms = start.elapsed().as_millis() as usize;
let mut hits = Vec::with_capacity(self.limit); let mut hits = Vec::with_capacity(self.limit);

View File

@ -115,7 +115,7 @@ pub fn load_routes(app: &mut tide::Server<Data>) {
.delete(|ctx| into_response(stop_words::delete(ctx))); .delete(|ctx| into_response(stop_words::delete(ctx)));
app.at("/indexes/:index/stats") app.at("/indexes/:index/stats")
.get(|ctx| into_response(stats::index_stat(ctx))); .get(|ctx| into_response(stats::index_stats(ctx)));
app.at("/keys/") app.at("/keys/")
.get(|ctx| into_response(key::list(ctx))) .get(|ctx| into_response(key::list(ctx)))

View File

@ -64,7 +64,7 @@ pub async fn search_with_url_query(ctx: Request<Data>) -> SResult<Response> {
let attributes_to_crop = schema let attributes_to_crop = schema
.displayed_name() .displayed_name()
.iter() .iter()
.map(|attr| ((*attr).to_string(), crop_length)) .map(|attr| (attr.to_string(), crop_length))
.collect(); .collect();
search_builder.attributes_to_crop(attributes_to_crop); search_builder.attributes_to_crop(attributes_to_crop);
} else { } else {
@ -81,7 +81,7 @@ pub async fn search_with_url_query(ctx: Request<Data>) -> SResult<Response> {
schema schema
.displayed_name() .displayed_name()
.iter() .iter()
.map(|s| (*s).to_string()) .map(|s| s.to_string())
.collect() .collect()
} else { } else {
attributes_to_highlight attributes_to_highlight

View File

@ -21,7 +21,7 @@ struct IndexStatsResponse {
fields_frequency: HashMap<String, usize>, fields_frequency: HashMap<String, usize>,
} }
pub async fn index_stat(ctx: Request<Data>) -> SResult<Response> { pub async fn index_stats(ctx: Request<Data>) -> SResult<Response> {
ctx.is_allowed(Admin)?; ctx.is_allowed(Admin)?;
let index_uid = ctx.url_param("index")?; let index_uid = ctx.url_param("index")?;
let index = ctx.index()?; let index = ctx.index()?;

Binary file not shown.

Binary file not shown.

View File

@ -1,8 +1,6 @@
use std::collections::{HashMap, HashSet};
use serde::{Serialize, Deserialize};
use crate::{FieldsMap, FieldId, SResult, Error, IndexedPos}; use crate::{FieldsMap, FieldId, SResult, Error, IndexedPos};
use serde::{Serialize, Deserialize};
use std::collections::{HashMap, HashSet};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Schema { pub struct Schema {
@ -60,11 +58,11 @@ impl Schema {
self.fields_map.id(name).is_some() self.fields_map.id(name).is_some()
} }
pub fn get_or_create_empty(&mut self, name: &str) -> SResult<FieldId> { pub fn insert(&mut self, name: &str) -> SResult<FieldId> {
self.fields_map.insert(name) self.fields_map.insert(name)
} }
pub fn get_or_create(&mut self, name: &str) -> SResult<FieldId> { pub fn insert_and_index(&mut self, name: &str) -> SResult<FieldId> {
match self.fields_map.id(name) { match self.fields_map.id(name) {
Some(id) => { Some(id) => {
Ok(id) Ok(id)
@ -80,24 +78,24 @@ impl Schema {
} }
} }
pub fn ranked(&self) -> HashSet<FieldId> { pub fn ranked(&self) -> &HashSet<FieldId> {
self.ranked.clone() &self.ranked
} }
pub fn ranked_name(&self) -> HashSet<&str> { pub fn ranked_name(&self) -> HashSet<&str> {
self.ranked.iter().filter_map(|a| self.name(*a)).collect() self.ranked.iter().filter_map(|a| self.name(*a)).collect()
} }
pub fn displayed(&self) -> HashSet<FieldId> { pub fn displayed(&self) -> &HashSet<FieldId> {
self.displayed.clone() &self.displayed
} }
pub fn displayed_name(&self) -> HashSet<&str> { pub fn displayed_name(&self) -> HashSet<&str> {
self.displayed.iter().filter_map(|a| self.name(*a)).collect() self.displayed.iter().filter_map(|a| self.name(*a)).collect()
} }
pub fn indexed(&self) -> Vec<FieldId> { pub fn indexed(&self) -> &Vec<FieldId> {
self.indexed.clone() &self.indexed
} }
pub fn indexed_name(&self) -> Vec<&str> { pub fn indexed_name(&self) -> Vec<&str> {
@ -168,7 +166,7 @@ impl Schema {
} }
pub fn update_ranked<S: AsRef<str>>(&mut self, data: impl IntoIterator<Item = S>) -> SResult<()> { pub fn update_ranked<S: AsRef<str>>(&mut self, data: impl IntoIterator<Item = S>) -> SResult<()> {
self.ranked = HashSet::new(); self.ranked.clear();
for name in data { for name in data {
self.set_ranked(name.as_ref())?; self.set_ranked(name.as_ref())?;
} }
@ -176,7 +174,7 @@ impl Schema {
} }
pub fn update_displayed<S: AsRef<str>>(&mut self, data: impl IntoIterator<Item = S>) -> SResult<()> { pub fn update_displayed<S: AsRef<str>>(&mut self, data: impl IntoIterator<Item = S>) -> SResult<()> {
self.displayed = HashSet::new(); self.displayed.clear();
for name in data { for name in data {
self.set_displayed(name.as_ref())?; self.set_displayed(name.as_ref())?;
} }
@ -184,8 +182,8 @@ impl Schema {
} }
pub fn update_indexed<S: AsRef<str>>(&mut self, data: Vec<S>) -> SResult<()> { pub fn update_indexed<S: AsRef<str>>(&mut self, data: Vec<S>) -> SResult<()> {
self.indexed = Vec::new(); self.indexed.clear();
self.indexed_map = HashMap::new(); self.indexed_map.clear();
for name in data { for name in data {
self.set_indexed(name.as_ref())?; self.set_indexed(name.as_ref())?;
} }

View File

@ -28,7 +28,7 @@ pub struct DocIndex {
/// The attribute in the document where the word was found /// The attribute in the document where the word was found
/// along with the index in it. /// along with the index in it.
/// Is an IndexedPos and not FieldId. Must be convert each time. /// This is an IndexedPos and not a FieldId. Must be converted each time.
pub attribute: u16, pub attribute: u16,
pub word_index: u16, pub word_index: u16,