mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-30 00:55:00 +08:00
Implement the simplified NOT operator
This commit is contained in:
parent
01675771d5
commit
44744d9e67
@ -112,6 +112,7 @@ impl<'a> From<Span<'a>> for Token<'a> {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum FilterCondition<'a> {
|
pub enum FilterCondition<'a> {
|
||||||
|
Not(Box<Self>),
|
||||||
Condition { fid: Token<'a>, op: Condition<'a> },
|
Condition { fid: Token<'a>, op: Condition<'a> },
|
||||||
Or(Vec<Self>),
|
Or(Vec<Self>),
|
||||||
And(Vec<Self>),
|
And(Vec<Self>),
|
||||||
@ -148,24 +149,6 @@ impl<'a> FilterCondition<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn negate(self) -> FilterCondition<'a> {
|
|
||||||
use FilterCondition::*;
|
|
||||||
|
|
||||||
match self {
|
|
||||||
Condition { fid, op } => match op.negate() {
|
|
||||||
(op, None) => Condition { fid, op },
|
|
||||||
(a, Some(b)) => Or(vec![
|
|
||||||
Condition { fid: fid.clone(), op: a }.into(),
|
|
||||||
Condition { fid, op: b }.into(),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
Or(subfilters) => And(subfilters.into_iter().map(|x| x.negate().into()).collect()),
|
|
||||||
And(subfilters) => Or(subfilters.into_iter().map(|x| x.negate().into()).collect()),
|
|
||||||
GeoLowerThan { point, radius } => GeoGreaterThan { point, radius },
|
|
||||||
GeoGreaterThan { point, radius } => GeoLowerThan { point, radius },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse(input: &'a str) -> Result<Option<Self>, Error> {
|
pub fn parse(input: &'a str) -> Result<Option<Self>, Error> {
|
||||||
if input.trim().is_empty() {
|
if input.trim().is_empty() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
@ -219,7 +202,9 @@ fn parse_and(input: Span) -> IResult<FilterCondition> {
|
|||||||
/// If we parse a `NOT` we MUST parse something behind.
|
/// If we parse a `NOT` we MUST parse something behind.
|
||||||
fn parse_not(input: Span) -> IResult<FilterCondition> {
|
fn parse_not(input: Span) -> IResult<FilterCondition> {
|
||||||
alt((
|
alt((
|
||||||
map(preceded(ws(tuple((tag("NOT"), multispace1))), cut(parse_not)), |e| e.negate()),
|
map(preceded(ws(tuple((tag("NOT"), multispace1))), cut(parse_not)), |e| {
|
||||||
|
FilterCondition::Not(Box::new(e))
|
||||||
|
}),
|
||||||
parse_primary,
|
parse_primary,
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
@ -360,6 +360,16 @@ impl<'a> Filter<'a> {
|
|||||||
filterable_fields: &HashSet<String>,
|
filterable_fields: &HashSet<String>,
|
||||||
) -> Result<RoaringBitmap> {
|
) -> Result<RoaringBitmap> {
|
||||||
match &self.condition {
|
match &self.condition {
|
||||||
|
FilterCondition::Not(f) => {
|
||||||
|
let all_ids = index.documents_ids(rtxn)?;
|
||||||
|
let selected = Self::inner_evaluate(
|
||||||
|
&(f.as_ref().clone()).into(),
|
||||||
|
rtxn,
|
||||||
|
index,
|
||||||
|
filterable_fields,
|
||||||
|
)?;
|
||||||
|
return Ok(all_ids - selected);
|
||||||
|
}
|
||||||
FilterCondition::Condition { fid, op } => {
|
FilterCondition::Condition { fid, op } => {
|
||||||
if crate::is_faceted(fid.value(), filterable_fields) {
|
if crate::is_faceted(fid.value(), filterable_fields) {
|
||||||
let field_ids_map = index.fields_ids_map(rtxn)?;
|
let field_ids_map = index.fields_ids_map(rtxn)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user