combine name searches
This commit is contained in:
parent
11ad72a33f
commit
0e4c792542
@ -4,6 +4,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::filter::{build_filter, fallback_filter, CardFilter};
|
use crate::filter::{build_filter, fallback_filter, CardFilter};
|
||||||
|
use itertools::Itertools;
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{take_until1, take_while, take_while_m_n},
|
bytes::complete::{take_until1, take_while, take_while_m_n},
|
||||||
@ -17,8 +18,24 @@ use nom::{
|
|||||||
pub fn parse_filters(input: &str) -> Result<(Vec<RawCardFilter>, Vec<CardFilter>), String> {
|
pub fn parse_filters(input: &str) -> Result<(Vec<RawCardFilter>, Vec<CardFilter>), String> {
|
||||||
parse_raw_filters(input).map_err(|e| format!("Error while parsing filters “{input}”: {e:?}")).and_then(|(rest, mut v)| {
|
parse_raw_filters(input).map_err(|e| format!("Error while parsing filters “{input}”: {e:?}")).and_then(|(rest, mut v)| {
|
||||||
if rest.is_empty() {
|
if rest.is_empty() {
|
||||||
v.sort_unstable_by_key(|RawCardFilter(f, _, _)| *f as u8);
|
// Sorting must be stable or we can’t combine multiple name filters into one.
|
||||||
Ok((v.clone(), v.into_iter().map(|r| build_filter(r)).collect::<Result<Vec<_>, _>>()?))
|
v.sort_by_key(|RawCardFilter(f, _, _)| *f as u8);
|
||||||
|
// Combine multiple names searches into one search filter. This makes the readable query nicer
|
||||||
|
// (“Showing 21 results where name is ally and name is of and name is justice” becomes
|
||||||
|
// “Showing 21 results where name is ‘ally of justice’”)
|
||||||
|
// and improves search performance by only performing one String::contains.
|
||||||
|
// This could be done without allocating two vectors, but coalesce is just so much nicer.
|
||||||
|
v = v
|
||||||
|
.into_iter()
|
||||||
|
.coalesce(|a, b| match (&a, &b) {
|
||||||
|
(
|
||||||
|
RawCardFilter(Field::Name, Operator::Equal, Value::String(s1)),
|
||||||
|
RawCardFilter(Field::Name, Operator::Equal, Value::String(s2)),
|
||||||
|
) => Ok(RawCardFilter(Field::Name, Operator::Equal, Value::String(format!("{s1} {s2}")))),
|
||||||
|
_ => Err((a, b)),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Ok((v.clone(), v.clone().into_iter().map(|r| build_filter(r)).collect::<Result<Vec<_>, _>>()?))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Input was not fully parsed. Left over: “{rest}”"))
|
Err(format!("Input was not fully parsed. Left over: “{rest}”"))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user