Return a new error when the sort criteria is not sortable

This commit is contained in:
Kerollmops 2021-08-17 16:14:56 +02:00
parent 71602e0f1b
commit 1b7f6ea1e7
No known key found for this signature in database
GPG Key ID: 92ADA4E935E71FA4
3 changed files with 37 additions and 2 deletions

View File

@ -64,6 +64,15 @@ pub enum AscDesc {
Desc(String),
}
impl AscDesc {
pub fn field(&self) -> &str {
match self {
AscDesc::Asc(field) => field,
AscDesc::Desc(field) => field,
}
}
}
impl FromStr for AscDesc {
type Err = UserError;

View File

@ -58,6 +58,7 @@ pub enum UserError {
InvalidFacetsDistribution { invalid_facets_name: HashSet<String> },
InvalidFilter(pest::error::Error<ParserRule>),
InvalidFilterAttribute(pest::error::Error<ParserRule>),
InvalidSortableAttribute { field: String, valid_fields: HashSet<String> },
InvalidStoreFile,
MaxDatabaseSizeReached,
MissingDocumentId { document: Object },
@ -226,6 +227,15 @@ only composed of alphanumeric characters (a-z A-Z 0-9), hyphens (-) and undersco
)
}
Self::InvalidFilterAttribute(error) => error.fmt(f),
Self::InvalidSortableAttribute { field, valid_fields } => {
let valid_names =
valid_fields.iter().map(AsRef::as_ref).collect::<Vec<_>>().join(", ");
write!(
f,
"Attribute {} is not sortable, available sortable attributes are: {}",
field, valid_names
)
}
Self::MissingDocumentId { document } => {
let json = serde_json::to_string(document).unwrap();
write!(f, "document doesn't have an identifier {}", json)

View File

@ -19,6 +19,7 @@ pub use self::facet::{FacetDistribution, FacetNumberIter, FilterCondition, Opera
pub use self::matching_words::MatchingWords;
use self::query_tree::QueryTreeBuilder;
use crate::criterion::AscDesc;
use crate::error::UserError;
use crate::search::criteria::r#final::{Final, FinalResult};
use crate::{DocumentId, Index, Result};
@ -142,13 +143,28 @@ impl<'a> Search<'a> {
None => MatchingWords::default(),
};
// We check that we are allowed to use the sort criteria, we check
// that they are declared in the sortable fields.
let sortable_fields = self.index.sortable_fields(self.rtxn)?;
if let Some(sort_criteria) = &self.sort_criteria {
for asc_desc in sort_criteria {
let field = asc_desc.field();
if !sortable_fields.contains(field) {
return Err(UserError::InvalidSortableAttribute {
field: field.to_string(),
valid_fields: sortable_fields,
}
.into());
}
}
}
let criteria_builder = criteria::CriteriaBuilder::new(self.rtxn, self.index)?;
let sort_criteria = self.sort_criteria.clone();
let criteria = criteria_builder.build(
query_tree,
primitive_query,
filtered_candidates,
sort_criteria,
self.sort_criteria.clone(),
)?;
match self.index.distinct_field(self.rtxn)? {