mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-26 23:04:26 +01:00
fix the filterable fields
This commit is contained in:
parent
e5af3ac65c
commit
7483c7513a
@ -26,6 +26,7 @@ enum FilterError<'a> {
|
||||
BadGeoLat(f64),
|
||||
BadGeoLng(f64),
|
||||
Reserved(&'a str),
|
||||
InternalError,
|
||||
}
|
||||
impl<'a> std::error::Error for FilterError<'a> {}
|
||||
|
||||
@ -46,6 +47,7 @@ impl<'a> Display for FilterError<'a> {
|
||||
Self::BadGeo(keyword) => write!(f, "`{}` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.", keyword),
|
||||
Self::BadGeoLat(lat) => write!(f, "Bad latitude `{}`. Latitude must be contained between -90 and 90 degrees. ", lat),
|
||||
Self::BadGeoLng(lng) => write!(f, "Bad longitude `{}`. Longitude must be contained between -180 and 180 degrees. ", lng),
|
||||
Self::InternalError => write!(f, "Internal error while executing this filter."),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -315,9 +317,14 @@ impl<'a> Filter<'a> {
|
||||
|
||||
match &self.condition {
|
||||
FilterCondition::Condition { fid, op } => {
|
||||
let filterable_fields = index.fields_ids_map(rtxn)?;
|
||||
if let Some(fid) = filterable_fields.id(&fid.inner.to_lowercase()) {
|
||||
Self::evaluate_operator(rtxn, index, numbers_db, strings_db, fid, &op)
|
||||
let filterable_fields = index.filterable_fields(rtxn)?;
|
||||
if filterable_fields.contains(&fid.inner.to_lowercase()) {
|
||||
let field_ids_map = index.fields_ids_map(rtxn)?;
|
||||
if let Some(fid) = field_ids_map.id(fid.inner) {
|
||||
Self::evaluate_operator(rtxn, index, numbers_db, strings_db, fid, &op)
|
||||
} else {
|
||||
return Err(fid.as_external_error(FilterError::InternalError))?;
|
||||
}
|
||||
} else {
|
||||
match fid.inner {
|
||||
attribute @ "_geo" => {
|
||||
@ -334,8 +341,7 @@ impl<'a> Filter<'a> {
|
||||
FilterError::AttributeNotFilterable {
|
||||
attribute,
|
||||
filterable: filterable_fields
|
||||
.iter()
|
||||
.map(|(_, s)| s)
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
},
|
||||
@ -356,8 +362,8 @@ impl<'a> Filter<'a> {
|
||||
}
|
||||
FilterCondition::Empty => Ok(RoaringBitmap::new()),
|
||||
FilterCondition::GeoLowerThan { point, radius } => {
|
||||
let filterable_fields = index.fields_ids_map(rtxn)?;
|
||||
if filterable_fields.id("_geo").is_some() {
|
||||
let filterable_fields = index.filterable_fields(rtxn)?;
|
||||
if filterable_fields.contains("_geo") {
|
||||
let base_point: [f64; 2] = [point[0].parse()?, point[1].parse()?];
|
||||
if !(-90.0..=90.0).contains(&base_point[0]) {
|
||||
return Err(
|
||||
@ -387,11 +393,7 @@ impl<'a> Filter<'a> {
|
||||
} else {
|
||||
return Err(point[0].as_external_error(FilterError::AttributeNotFilterable {
|
||||
attribute: "_geo",
|
||||
filterable: filterable_fields
|
||||
.iter()
|
||||
.map(|(_, s)| s)
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
filterable: filterable_fields.into_iter().collect::<Vec<_>>().join(" "),
|
||||
}))?;
|
||||
}
|
||||
}
|
||||
@ -487,6 +489,50 @@ mod tests {
|
||||
assert_eq!(condition, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_filterable() {
|
||||
let path = tempfile::tempdir().unwrap();
|
||||
let mut options = EnvOpenOptions::new();
|
||||
options.map_size(10 * 1024 * 1024); // 10 MB
|
||||
let index = Index::new(options, &path).unwrap();
|
||||
|
||||
let rtxn = index.read_txn().unwrap();
|
||||
let filter = Filter::from_str("_geoRadius(42, 150, 10)").unwrap();
|
||||
let error = filter.evaluate(&rtxn, &index).unwrap_err();
|
||||
assert!(error.to_string().starts_with(
|
||||
"Attribute `_geo` is not filterable. Available filterable attributes are: ``."
|
||||
));
|
||||
|
||||
let filter = Filter::from_str("dog = \"bernese mountain\"").unwrap();
|
||||
let error = filter.evaluate(&rtxn, &index).unwrap_err();
|
||||
assert!(error.to_string().starts_with(
|
||||
"Attribute `dog` is not filterable. Available filterable attributes are: ``."
|
||||
));
|
||||
drop(rtxn);
|
||||
|
||||
// Set the filterable fields to be the channel.
|
||||
let mut wtxn = index.write_txn().unwrap();
|
||||
let mut builder = Settings::new(&mut wtxn, &index, 0);
|
||||
builder.set_searchable_fields(vec![S("title")]);
|
||||
builder.set_filterable_fields(hashset! { S("title") });
|
||||
builder.execute(|_, _| ()).unwrap();
|
||||
wtxn.commit().unwrap();
|
||||
|
||||
let rtxn = index.read_txn().unwrap();
|
||||
|
||||
let filter = Filter::from_str("_geoRadius(-100, 150, 10)").unwrap();
|
||||
let error = filter.evaluate(&rtxn, &index).unwrap_err();
|
||||
assert!(error.to_string().starts_with(
|
||||
"Attribute `_geo` is not filterable. Available filterable attributes are: `title`."
|
||||
));
|
||||
|
||||
let filter = Filter::from_str("name = 12").unwrap();
|
||||
let error = filter.evaluate(&rtxn, &index).unwrap_err();
|
||||
assert!(error.to_string().starts_with(
|
||||
"Attribute `name` is not filterable. Available filterable attributes are: `title`."
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn geo_radius_error() {
|
||||
let path = tempfile::tempdir().unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user