From cd3c0d750c51b7c57d2984caba7d09df736d07a5 Mon Sep 17 00:00:00 2001 From: mposmta Date: Mon, 20 Apr 2020 16:00:35 +0200 Subject: [PATCH] Add support for filtering on arrays of strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit update changelog Update CHANGELOG.md Co-Authored-By: Clément Renault fix requested changes --- CHANGELOG.md | 1 + meilisearch-core/src/filters/condition.rs | 36 +++++++++++++++-------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 312e6645a..6fb58843a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## v0.10.1 (unreleased) - Add '@' character as tokenizer separator (#607) + - Add support for filtering on arrays of strings (#611) ## v0.10 diff --git a/meilisearch-core/src/filters/condition.rs b/meilisearch-core/src/filters/condition.rs index 1f2d2c989..0045e410f 100644 --- a/meilisearch-core/src/filters/condition.rs +++ b/meilisearch-core/src/filters/condition.rs @@ -10,7 +10,7 @@ use pest::iterators::Pair; use serde_json::{Value, Number}; use super::parser::Rule; -#[derive(Debug)] +#[derive(Debug, PartialEq)] enum ConditionType { Greater, Less, @@ -160,12 +160,19 @@ impl<'a> Condition<'a> { document_id: DocumentId, ) -> Result { match index.document_attribute::(reader, document_id, self.field)? { + Some(Value::Array(values)) => Ok(values.iter().any(|v| self.match_value(Some(v)))), + other => Ok(self.match_value(other.as_ref())), + } + } + + fn match_value(&self, value: Option<&Value>) -> bool { + match value { Some(Value::String(s)) => { let value = self.value.as_str(); match self.condition { - ConditionType::Equal => Ok(unicase::eq(value, &s)), - ConditionType::NotEqual => Ok(!unicase::eq(value, &s)), - _ => Ok(false) + ConditionType::Equal => unicase::eq(value, &s), + ConditionType::NotEqual => !unicase::eq(value, &s), + _ => false } }, Some(Value::Number(n)) => { @@ -179,22 +186,25 @@ impl<'a> Condition<'a> { ConditionType::Greater => ord == Ordering::Greater, ConditionType::Less => ord == Ordering::Less, }; - return Ok(res) + return res } } - Ok(false) + false }, Some(Value::Bool(b)) => { if let Some(value) = self.value.as_bool() { - return match self.condition { - ConditionType::Equal => Ok(b == value), - ConditionType::NotEqual => Ok(b != value), - _ => Ok(false) - } + let res = match self.condition { + ConditionType::Equal => *b == value, + ConditionType::NotEqual => *b != value, + _ => false + }; + return res } - Ok(false) + false }, - _ => Ok(false), + // if field is not supported (or not found), all values are different from it, + // so != should always return true in this case. + _ => self.condition == ConditionType::NotEqual, } } }