diff --git a/filter-parser/src/lib.rs b/filter-parser/src/lib.rs index 12edd56c8..31ca2919a 100644 --- a/filter-parser/src/lib.rs +++ b/filter-parser/src/lib.rs @@ -164,10 +164,8 @@ fn ws<'a, O>(inner: impl FnMut(Span<'a>) -> IResult) -> impl FnMut(Span<'a>) delimited(multispace0, inner, multispace0) } - /// value_list = (value ("," value)* ","?)? fn parse_value_list<'a>(input: Span<'a>) -> IResult>> { - // TODO: here, I should return a failure with a clear explanation whenever possible // for example: // * expected the name of a field, but got `AND` @@ -193,12 +191,13 @@ fn parse_in(input: Span) -> IResult { let (input, _) = ws(tag("IN"))(input)?; // everything after `IN` can be a failure - let (input, _) = cut_with_err(tag("["), |_| { - Error::new_from_kind(input, ErrorKind::InOpeningBracket) - })(input)?; + let (input, _) = + cut_with_err(tag("["), |_| Error::new_from_kind(input, ErrorKind::InOpeningBracket))( + input, + )?; let (input, content) = cut(parse_value_list)(input)?; - + // everything after `IN` can be a failure let (input, _) = cut_with_err(tag("]"), |_| { if eof::<_, ()>(input).is_ok() { @@ -218,18 +217,19 @@ fn parse_not_in(input: Span) -> IResult { let (input, _) = multispace1(input)?; let (input, _) = ws(tag("IN"))(input)?; - // everything after `IN` can be a failure - let (input, _) = cut_with_err(tag("["), |_| { - Error::new_from_kind(input, ErrorKind::InOpeningBracket) - })(input)?; + let (input, _) = + cut_with_err(tag("["), |_| Error::new_from_kind(input, ErrorKind::InOpeningBracket))( + input, + )?; let (input, content) = cut(parse_value_list)(input)?; - + // everything after `IN` can be a failure - let (input, _) = cut_with_err(tag("]"), |_| { - Error::new_from_kind(input, ErrorKind::InClosingBracket) - })(input)?; + let (input, _) = + cut_with_err(tag("]"), |_| Error::new_from_kind(input, ErrorKind::InClosingBracket))( + input, + )?; let filter = FilterCondition::Not(Box::new(FilterCondition::In { fid: value, els: content })); Ok((input, filter)) @@ -378,60 +378,60 @@ pub mod tests { // simple test ( "x = AND", - Fc::Not(Box::new(Fc::Not(Box::new(Fc::In { - fid: rtok("NOT NOT", "colour"), - els: vec![] + Fc::Not(Box::new(Fc::Not(Box::new(Fc::In { + fid: rtok("NOT NOT", "colour"), + els: vec![] })))) ), ( "colour IN[]", - Fc::In { - fid: rtok("", "colour"), - els: vec![] + Fc::In { + fid: rtok("", "colour"), + els: vec![] } ), ( "colour IN[green]", - Fc::In { - fid: rtok("", "colour"), - els: vec![rtok("colour IN[", "green")] + Fc::In { + fid: rtok("", "colour"), + els: vec![rtok("colour IN[", "green")] } ), ( "colour IN[green,]", - Fc::In { - fid: rtok("", "colour"), - els: vec![rtok("colour IN[", "green")] + Fc::In { + fid: rtok("", "colour"), + els: vec![rtok("colour IN[", "green")] } ), ( "colour IN[green,blue]", - Fc::In { - fid: rtok("", "colour"), + Fc::In { + fid: rtok("", "colour"), els: vec![ rtok("colour IN[", "green"), rtok("colour IN[green, ", "blue"), - ] + ] } ), ( "colour NOT IN[green,blue]", - Fc::Not(Box::new(Fc::In { - fid: rtok("", "colour"), + Fc::Not(Box::new(Fc::In { + fid: rtok("", "colour"), els: vec![ rtok("colour NOT IN[", "green"), rtok("colour NOT IN[green, ", "blue"), - ] + ] })) ), ( " colour IN [ green , blue , ]", - Fc::In { - fid: rtok(" ", "colour"), + Fc::In { + fid: rtok(" ", "colour"), els: vec![ rtok("colour IN [ ", "green"), rtok("colour IN [ green , ", "blue"), - ] + ] } ), ( diff --git a/milli/src/search/facet/filter.rs b/milli/src/search/facet/filter.rs index 25ffe1842..487676f4a 100644 --- a/milli/src/search/facet/filter.rs +++ b/milli/src/search/facet/filter.rs @@ -302,9 +302,7 @@ impl<'a> Filter<'a> { } Condition::NotEqual(val) => { let operator = Condition::Equal(val.clone()); - let docids = Self::evaluate_operator( - rtxn, index, field_id, &operator, - )?; + let docids = Self::evaluate_operator(rtxn, index, field_id, &operator)?; let all_ids = index.documents_ids(rtxn)?; return Ok(all_ids - docids); } @@ -421,20 +419,30 @@ impl<'a> Filter<'a> { FilterCondition::Or(subfilters) => { let mut bitmap = RoaringBitmap::new(); for f in subfilters { - bitmap |= Self::inner_evaluate(&(f.clone()).into(), rtxn, index, filterable_fields)?; + bitmap |= + Self::inner_evaluate(&(f.clone()).into(), rtxn, index, filterable_fields)?; } Ok(bitmap) } FilterCondition::And(subfilters) => { let mut subfilters_iter = subfilters.iter(); if let Some(first_subfilter) = subfilters_iter.next() { - let mut bitmap = - Self::inner_evaluate(&(first_subfilter.clone()).into(), rtxn, index, filterable_fields)?; + let mut bitmap = Self::inner_evaluate( + &(first_subfilter.clone()).into(), + rtxn, + index, + filterable_fields, + )?; for f in subfilters_iter { if bitmap.is_empty() { return Ok(bitmap); } - bitmap &= Self::inner_evaluate(&(f.clone()).into(), rtxn, index, filterable_fields)?; + bitmap &= Self::inner_evaluate( + &(f.clone()).into(), + rtxn, + index, + filterable_fields, + )?; } Ok(bitmap) } else {