mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-23 02:27:40 +08:00
Simplify FilterCondition code, made possible by the new NOT operator
This commit is contained in:
parent
44744d9e67
commit
cc7415bb31
@ -21,30 +21,12 @@ pub enum Condition<'a> {
|
|||||||
Equal(Token<'a>),
|
Equal(Token<'a>),
|
||||||
NotEqual(Token<'a>),
|
NotEqual(Token<'a>),
|
||||||
Exists,
|
Exists,
|
||||||
NotExists,
|
|
||||||
LowerThan(Token<'a>),
|
LowerThan(Token<'a>),
|
||||||
LowerThanOrEqual(Token<'a>),
|
LowerThanOrEqual(Token<'a>),
|
||||||
Between { from: Token<'a>, to: Token<'a> },
|
Between { from: Token<'a>, to: Token<'a> },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Condition<'a> {
|
/// condition = value ("==" | ">" ...) value
|
||||||
/// This method can return two operations in case it must express
|
|
||||||
/// an OR operation for the between case (i.e. `TO`).
|
|
||||||
pub fn negate(self) -> (Self, Option<Self>) {
|
|
||||||
match self {
|
|
||||||
GreaterThan(n) => (LowerThanOrEqual(n), None),
|
|
||||||
GreaterThanOrEqual(n) => (LowerThan(n), None),
|
|
||||||
Equal(s) => (NotEqual(s), None),
|
|
||||||
NotEqual(s) => (Equal(s), None),
|
|
||||||
Exists => (NotExists, None),
|
|
||||||
NotExists => (Exists, None),
|
|
||||||
LowerThan(n) => (GreaterThanOrEqual(n), None),
|
|
||||||
LowerThanOrEqual(n) => (GreaterThan(n), None),
|
|
||||||
Between { from, to } => (LowerThan(from), Some(GreaterThan(to))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// condition = value ("=" | "!=" | ">" | ">=" | "<" | "<=") value
|
|
||||||
pub fn parse_condition(input: Span) -> IResult<FilterCondition> {
|
pub fn parse_condition(input: Span) -> IResult<FilterCondition> {
|
||||||
let operator = alt((tag("<="), tag(">="), tag("!="), tag("<"), tag(">"), tag("=")));
|
let operator = alt((tag("<="), tag(">="), tag("!="), tag("<"), tag(">"), tag("=")));
|
||||||
let (input, (fid, op, value)) = tuple((parse_value, operator, cut(parse_value)))(input)?;
|
let (input, (fid, op, value)) = tuple((parse_value, operator, cut(parse_value)))(input)?;
|
||||||
@ -73,7 +55,10 @@ pub fn parse_not_exists(input: Span) -> IResult<FilterCondition> {
|
|||||||
let (input, key) = parse_value(input)?;
|
let (input, key) = parse_value(input)?;
|
||||||
|
|
||||||
let (input, _) = tuple((tag("NOT"), multispace1, tag("EXISTS")))(input)?;
|
let (input, _) = tuple((tag("NOT"), multispace1, tag("EXISTS")))(input)?;
|
||||||
Ok((input, FilterCondition::Condition { fid: key.into(), op: NotExists }))
|
Ok((
|
||||||
|
input,
|
||||||
|
FilterCondition::Not(Box::new(FilterCondition::Condition { fid: key.into(), op: Exists })),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// to = value value "TO" WS+ value
|
/// to = value value "TO" WS+ value
|
||||||
|
@ -117,7 +117,6 @@ pub enum FilterCondition<'a> {
|
|||||||
Or(Vec<Self>),
|
Or(Vec<Self>),
|
||||||
And(Vec<Self>),
|
And(Vec<Self>),
|
||||||
GeoLowerThan { point: [Token<'a>; 2], radius: Token<'a> },
|
GeoLowerThan { point: [Token<'a>; 2], radius: Token<'a> },
|
||||||
GeoGreaterThan { point: [Token<'a>; 2], radius: Token<'a> },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FilterCondition<'a> {
|
impl<'a> FilterCondition<'a> {
|
||||||
@ -144,7 +143,6 @@ impl<'a> FilterCondition<'a> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
FilterCondition::GeoLowerThan { point: [point, _], .. } if depth == 0 => Some(point),
|
FilterCondition::GeoLowerThan { point: [point, _], .. } if depth == 0 => Some(point),
|
||||||
FilterCondition::GeoGreaterThan { point: [point, _], .. } if depth == 0 => Some(point),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,17 +441,17 @@ pub mod tests {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"NOT subscribers EXISTS",
|
"NOT subscribers EXISTS",
|
||||||
Fc::Condition {
|
Fc::Not(Box::new(Fc::Condition {
|
||||||
fid: rtok("NOT ", "subscribers"),
|
fid: rtok("NOT ", "subscribers"),
|
||||||
op: Condition::NotExists,
|
op: Condition::Exists,
|
||||||
},
|
})),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"subscribers NOT EXISTS",
|
"subscribers NOT EXISTS",
|
||||||
Fc::Condition {
|
Fc::Not(Box::new(Fc::Condition {
|
||||||
fid: rtok("", "subscribers"),
|
fid: rtok("", "subscribers"),
|
||||||
op: Condition::NotExists,
|
op: Condition::Exists,
|
||||||
},
|
})),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"NOT subscribers NOT EXISTS",
|
"NOT subscribers NOT EXISTS",
|
||||||
@ -464,10 +462,10 @@ pub mod tests {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"subscribers NOT EXISTS",
|
"subscribers NOT EXISTS",
|
||||||
Fc::Condition {
|
Fc::Not(Box::new(Fc::Condition {
|
||||||
fid: rtok("", "subscribers"),
|
fid: rtok("", "subscribers"),
|
||||||
op: Condition::NotExists,
|
op: Condition::Exists,
|
||||||
},
|
})),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"subscribers 100 TO 1000",
|
"subscribers 100 TO 1000",
|
||||||
@ -503,10 +501,10 @@ pub mod tests {
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"NOT _geoRadius(12, 13, 14)",
|
"NOT _geoRadius(12, 13, 14)",
|
||||||
Fc::GeoGreaterThan {
|
Fc::Not(Box::new(Fc::GeoLowerThan {
|
||||||
point: [rtok("NOT _geoRadius(", "12"), rtok("NOT _geoRadius(12, ", "13")],
|
point: [rtok("NOT _geoRadius(", "12"), rtok("NOT _geoRadius(12, ", "13")],
|
||||||
radius: rtok("NOT _geoRadius(12, 13, ", "14"),
|
radius: rtok("NOT _geoRadius(12, 13, ", "14"),
|
||||||
},
|
})),
|
||||||
),
|
),
|
||||||
// test simple `or` and `and`
|
// test simple `or` and `and`
|
||||||
(
|
(
|
||||||
|
@ -276,14 +276,6 @@ impl<'a> Filter<'a> {
|
|||||||
let exist = index.exists_faceted_documents_ids(rtxn, field_id)?;
|
let exist = index.exists_faceted_documents_ids(rtxn, field_id)?;
|
||||||
return Ok(exist);
|
return Ok(exist);
|
||||||
}
|
}
|
||||||
Condition::NotExists => {
|
|
||||||
let all_ids = index.documents_ids(rtxn)?;
|
|
||||||
|
|
||||||
let exist = Self::evaluate_operator(rtxn, index, field_id, &Condition::Exists)?;
|
|
||||||
|
|
||||||
let notexist = all_ids - exist;
|
|
||||||
return Ok(notexist);
|
|
||||||
}
|
|
||||||
Condition::Equal(val) => {
|
Condition::Equal(val) => {
|
||||||
let (_original_value, string_docids) = strings_db
|
let (_original_value, string_docids) = strings_db
|
||||||
.get(rtxn, &(field_id, &val.value().to_lowercase()))?
|
.get(rtxn, &(field_id, &val.value().to_lowercase()))?
|
||||||
@ -460,17 +452,6 @@ impl<'a> Filter<'a> {
|
|||||||
}))?;
|
}))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FilterCondition::GeoGreaterThan { point, radius } => {
|
|
||||||
let result = Self::inner_evaluate(
|
|
||||||
&FilterCondition::GeoLowerThan { point: point.clone(), radius: radius.clone() }
|
|
||||||
.into(),
|
|
||||||
rtxn,
|
|
||||||
index,
|
|
||||||
filterable_fields,
|
|
||||||
)?;
|
|
||||||
let geo_faceted_doc_ids = index.geo_faceted_documents_ids(rtxn)?;
|
|
||||||
Ok(geo_faceted_doc_ids - result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user