mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-23 10:37:41 +08:00
Merge pull request #400 from meilisearch/fix-issues
Close multiples issues on HTTP behavior
This commit is contained in:
commit
70f18a8086
@ -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(
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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) => {
|
||||||
|
@ -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 = ¤t_settings.ranking_rules;
|
let ranking_rules = ¤t_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) {
|
||||||
|
@ -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(())
|
||||||
|
@ -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) {
|
||||||
|
@ -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(¤t_settings).unwrap();
|
let bytes = bincode::serialize(¤t_settings).unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user