diff --git a/query-grammar/src/query_grammar.rs b/query-grammar/src/query_grammar.rs index ade1fb2f3..4bc992bae 100644 --- a/query-grammar/src/query_grammar.rs +++ b/query-grammar/src/query_grammar.rs @@ -321,7 +321,17 @@ fn exists(inp: &str) -> IResult<&str, UserInputLeaf> { UserInputLeaf::Exists { field: String::new(), }, - tuple((multispace0, char('*'), peek(alt((multispace1, eof))))), + tuple(( + multispace0, + char('*'), + peek(alt(( + value( + "", + satisfy(|c: char| c.is_whitespace() || ESCAPE_IN_WORD.contains(&c)), + ), + eof, + ))), + )), )(inp) } @@ -332,7 +342,13 @@ fn exists_precond(inp: &str) -> IResult<&str, (), ()> { field_name, multispace0, char('*'), - peek(alt((multispace1, eof))), // we need to check this isn't a wildcard query + peek(alt(( + value( + "", + satisfy(|c: char| c.is_whitespace() || ESCAPE_IN_WORD.contains(&c)), + ), + eof, + ))), // we need to check this isn't a wildcard query ))), )(inp) .map_err(|e| e.map(|_| ())) @@ -1625,8 +1641,14 @@ mod test { #[test] fn test_exist_query() { - test_parse_query_to_ast_helper("a:*", "\"a\":*"); - test_parse_query_to_ast_helper("a: *", "\"a\":*"); + test_parse_query_to_ast_helper("a:*", "$exists(\"a\")"); + test_parse_query_to_ast_helper("a: *", "$exists(\"a\")"); + + test_parse_query_to_ast_helper( + "(hello AND toto:*) OR happy", + "(?(+hello +$exists(\"toto\")) ?happy)", + ); + test_parse_query_to_ast_helper("(a:*)", "$exists(\"a\")"); // these are term/wildcard query (not a phrase prefix) test_parse_query_to_ast_helper("a:b*", "\"a\":b*"); diff --git a/query-grammar/src/user_input_ast.rs b/query-grammar/src/user_input_ast.rs index 4f09feb38..552deb5d4 100644 --- a/query-grammar/src/user_input_ast.rs +++ b/query-grammar/src/user_input_ast.rs @@ -101,7 +101,7 @@ impl Debug for UserInputLeaf { } UserInputLeaf::All => write!(formatter, "*"), UserInputLeaf::Exists { field } => { - write!(formatter, "\"{field}\":*") + write!(formatter, "$exists(\"{field}\")") } } }