Merge pull request #400 from meilisearch/fix-issues

Close multiples issues on HTTP behavior
This commit is contained in:
Clément Renault 2019-12-13 10:30:42 +01:00 committed by GitHub
commit 70f18a8086
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 54 deletions

View File

@ -24,9 +24,7 @@ impl<'a> ser::Serializer for Indexer<'a> {
type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>; type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>;
fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> { fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::UnindexableType { Ok(None)
type_name: "boolean",
})
} }
fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> { fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
@ -96,9 +94,7 @@ impl<'a> ser::Serializer for Indexer<'a> {
} }
fn serialize_none(self) -> Result<Self::Ok, Self::Error> { fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::UnindexableType { Ok(None)
type_name: "Option",
})
} }
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
@ -113,13 +109,11 @@ impl<'a> ser::Serializer for Indexer<'a> {
} }
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::UnindexableType { type_name: "()" }) Ok(None)
} }
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> { fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::UnindexableType { Ok(None)
type_name: "unit struct",
})
} }
fn serialize_unit_variant( fn serialize_unit_variant(
@ -128,9 +122,7 @@ impl<'a> ser::Serializer for Indexer<'a> {
_variant_index: u32, _variant_index: u32,
_variant: &'static str, _variant: &'static str,
) -> Result<Self::Ok, Self::Error> { ) -> Result<Self::Ok, Self::Error> {
Err(SerializerError::UnindexableType { Ok(None)
type_name: "unit variant",
})
} }
fn serialize_newtype_struct<T: ?Sized>( fn serialize_newtype_struct<T: ?Sized>(
@ -219,9 +211,14 @@ impl<'a> ser::Serializer for Indexer<'a> {
_name: &'static str, _name: &'static str,
_len: usize, _len: usize,
) -> Result<Self::SerializeStruct, Self::Error> { ) -> Result<Self::SerializeStruct, Self::Error> {
Err(SerializerError::UnindexableType { let indexer = StructIndexer {
type_name: "struct", attribute: self.attribute,
}) document_id: self.document_id,
indexer: self.indexer,
texts: Vec::new(),
};
Ok(indexer)
} }
fn serialize_struct_variant( fn serialize_struct_variant(

View File

@ -101,14 +101,18 @@ pub fn apply_stop_words_deletion(
// now that we have setup the stop words // now that we have setup the stop words
// lets reindex everything... // lets reindex everything...
reindex_all_documents( if let Ok(number) = main_store.number_of_documents(writer) {
writer, if number > 0 {
main_store, reindex_all_documents(
documents_fields_store, writer,
documents_fields_counts_store, main_store,
postings_lists_store, documents_fields_store,
docs_words_store, documents_fields_counts_store,
)?; postings_lists_store,
docs_words_store,
)?;
}
}
Ok(()) Ok(())
} }

View File

@ -79,7 +79,7 @@ impl IntoResponse for ResponseError {
error(err, StatusCode::BAD_REQUEST) error(err, StatusCode::BAD_REQUEST)
} }
ResponseError::InvalidToken(err) => { ResponseError::InvalidToken(err) => {
error(format!("Invalid Token: {}", err), StatusCode::FORBIDDEN) error(format!("Invalid API key: {}", err), StatusCode::FORBIDDEN)
} }
ResponseError::NotFound(err) => error(err, StatusCode::NOT_FOUND), ResponseError::NotFound(err) => error(err, StatusCode::NOT_FOUND),
ResponseError::IndexNotFound(index) => { ResponseError::IndexNotFound(index) => {

View File

@ -1,6 +1,6 @@
use crate::routes::setting::{RankingOrdering, SettingBody}; use crate::routes::setting::{RankingOrdering, Setting};
use indexmap::IndexMap; use indexmap::IndexMap;
use log::error; use log::{error, warn};
use meilisearch_core::criterion::*; use meilisearch_core::criterion::*;
use meilisearch_core::Highlight; use meilisearch_core::Highlight;
use meilisearch_core::{Index, RankedMap}; use meilisearch_core::{Index, RankedMap};
@ -243,7 +243,14 @@ impl<'a> SearchBuilder<'a> {
.map_err(|e| Error::RetrieveDocument(doc.id.0, e.to_string()))? .map_err(|e| Error::RetrieveDocument(doc.id.0, e.to_string()))?
.ok_or(Error::DocumentNotFound(doc.id.0))?; .ok_or(Error::DocumentNotFound(doc.id.0))?;
let mut formatted = document.clone(); let has_attributes_to_highlight = self.attributes_to_highlight.is_some();
let has_attributes_to_crop = self.attributes_to_crop.is_some();
let mut formatted = if has_attributes_to_highlight || has_attributes_to_crop {
document.clone()
} else {
IndexMap::new()
};
let mut matches = doc.highlights.clone(); let mut matches = doc.highlights.clone();
// Crops fields if needed // Crops fields if needed
@ -292,7 +299,7 @@ impl<'a> SearchBuilder<'a> {
) -> Result<Option<Criteria<'a>>, Error> { ) -> Result<Option<Criteria<'a>>, Error> {
let current_settings = match self.index.main.customs(reader).unwrap() { let current_settings = match self.index.main.customs(reader).unwrap() {
Some(bytes) => bincode::deserialize(bytes).unwrap(), Some(bytes) => bincode::deserialize(bytes).unwrap(),
None => SettingBody::default(), None => Setting::default(),
}; };
let ranking_rules = &current_settings.ranking_rules; let ranking_rules = &current_settings.ranking_rules;
@ -342,13 +349,19 @@ impl<'a> SearchBuilder<'a> {
for (rule, order) in ranking_rules.iter() { for (rule, order) in ranking_rules.iter() {
let custom_ranking = match order { let custom_ranking = match order {
RankingOrdering::Asc => { RankingOrdering::Asc => {
SortByAttr::lower_is_better(&ranked_map, &schema, &rule).unwrap() SortByAttr::lower_is_better(&ranked_map, &schema, &rule)
} }
RankingOrdering::Dsc => { RankingOrdering::Dsc => {
SortByAttr::higher_is_better(&ranked_map, &schema, &rule).unwrap() SortByAttr::higher_is_better(&ranked_map, &schema, &rule)
} }
}; };
builder.push(custom_ranking); if let Ok(custom_ranking) = custom_ranking {
builder.push(custom_ranking);
} else {
// TODO push this warning to a log tree
warn!("Custom ranking cannot be added; Attribute {} not registered for ranking", rule)
}
} }
builder.push(DocumentId); builder.push(DocumentId);
return Ok(Some(builder.build())); return Ok(Some(builder.build()));
@ -494,7 +507,7 @@ fn calculate_highlights(
matches: &MatchesInfos, matches: &MatchesInfos,
attributes_to_highlight: &HashSet<String>, attributes_to_highlight: &HashSet<String>,
) -> IndexMap<String, Value> { ) -> IndexMap<String, Value> {
let mut highlight_result = IndexMap::new(); let mut highlight_result = document.clone();
for (attribute, matches) in matches.iter() { for (attribute, matches) in matches.iter() {
if attributes_to_highlight.contains(attribute) { if attributes_to_highlight.contains(attribute) {

View File

@ -66,7 +66,7 @@ impl ContextExt for Context<Data> {
} }
if !token_config.acl.contains(&acl) { if !token_config.acl.contains(&acl) {
return Err(ResponseError::invalid_token("token do not have this ACL")); return Err(ResponseError::invalid_token("no permission"));
} }
Ok(()) Ok(())

View File

@ -390,19 +390,10 @@ pub async fn get_all_updates_status(ctx: Context<Data>) -> SResult<Response> {
pub async fn delete_index(ctx: Context<Data>) -> SResult<StatusCode> { pub async fn delete_index(ctx: Context<Data>) -> SResult<StatusCode> {
ctx.is_allowed(IndexesWrite)?; ctx.is_allowed(IndexesWrite)?;
let _ = ctx.index()?;
let index_uid = ctx.url_param("index")?; let index_uid = ctx.url_param("index")?;
ctx.state().db.delete_index(&index_uid).map_err(ResponseError::internal)?;
let found = ctx Ok(StatusCode::NO_CONTENT)
.state()
.db
.delete_index(&index_uid)
.map_err(ResponseError::internal)?;
if found {
Ok(StatusCode::NO_CONTENT)
} else {
Ok(StatusCode::NOT_FOUND)
}
} }
pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) { pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) {

View File

@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use http::StatusCode; use http::StatusCode;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize, Deserializer};
use tide::response::IntoResponse; use tide::response::IntoResponse;
use tide::{Context, Response}; use tide::{Context, Response};
@ -11,9 +11,9 @@ use crate::models::token::ACL::*;
use crate::routes::document::IndexUpdateResponse; use crate::routes::document::IndexUpdateResponse;
use crate::Data; use crate::Data;
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SettingBody { pub struct Setting {
pub ranking_order: Option<RankingOrder>, pub ranking_order: Option<RankingOrder>,
pub distinct_field: Option<DistinctField>, pub distinct_field: Option<DistinctField>,
pub ranking_rules: Option<RankingRules>, pub ranking_rules: Option<RankingRules>,
@ -39,12 +39,31 @@ pub async fn get(ctx: Context<Data>) -> SResult<Response> {
let settings = match index.main.customs(&reader).unwrap() { let settings = match index.main.customs(&reader).unwrap() {
Some(bytes) => bincode::deserialize(bytes).unwrap(), Some(bytes) => bincode::deserialize(bytes).unwrap(),
None => SettingBody::default(), None => Setting::default(),
}; };
Ok(tide::response::json(settings)) Ok(tide::response::json(settings))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SettingBody {
#[serde(default, deserialize_with = "deserialize_some")]
pub ranking_order: Option<Option<RankingOrder>>,
#[serde(default, deserialize_with = "deserialize_some")]
pub distinct_field: Option<Option<DistinctField>>,
#[serde(default, deserialize_with = "deserialize_some")]
pub ranking_rules: Option<Option<RankingRules>>,
}
// Any value that is present is considered Some value, including null.
fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
where T: Deserialize<'de>,
D: Deserializer<'de>
{
Deserialize::deserialize(deserializer).map(Some)
}
pub async fn update(mut ctx: Context<Data>) -> SResult<Response> { pub async fn update(mut ctx: Context<Data>) -> SResult<Response> {
ctx.is_allowed(SettingsWrite)?; ctx.is_allowed(SettingsWrite)?;
@ -58,19 +77,19 @@ pub async fn update(mut ctx: Context<Data>) -> SResult<Response> {
let mut current_settings = match index.main.customs(&reader).unwrap() { let mut current_settings = match index.main.customs(&reader).unwrap() {
Some(bytes) => bincode::deserialize(bytes).unwrap(), Some(bytes) => bincode::deserialize(bytes).unwrap(),
None => SettingBody::default(), None => Setting::default(),
}; };
if let Some(ranking_order) = settings.ranking_order { if let Some(ranking_order) = settings.ranking_order {
current_settings.ranking_order = Some(ranking_order); current_settings.ranking_order = ranking_order;
} }
if let Some(distinct_field) = settings.distinct_field { if let Some(distinct_field) = settings.distinct_field {
current_settings.distinct_field = Some(distinct_field); current_settings.distinct_field = distinct_field;
} }
if let Some(ranking_rules) = settings.ranking_rules { if let Some(ranking_rules) = settings.ranking_rules {
current_settings.ranking_rules = Some(ranking_rules); current_settings.ranking_rules = ranking_rules;
} }
let bytes = bincode::serialize(&current_settings).unwrap(); let bytes = bincode::serialize(&current_settings).unwrap();