In my Node.js web application, I have created a grammar using peg.js for simple search queries. The challenge I am facing is translating the Abstract Syntax Tree (AST) it generates into a $match
parameter for MongoDB's aggregate function. Most scenarios work well, but I'm struggling with how to represent NOT (A AND B)
in MongoDB.
Here are some sample data:
{ _id:123, labels:['a', 'b', 'c'], tags:['g', 'h', 'i']},
{ _id:456, labels:['a', 'e', 'f'], tags:['i', 'j', 'k']},
{ _id:789, labels:['c', 'd', 'b'], tags:['h', 'l', 'm']}
A user may input queries like NOT (labels:a AND labels:b)
or NOT (labels:b AND tags:h)
, both of which are valid based on my grammar.
The first query aims to retrieve documents that do not contain both 'a' and 'b' in their labels
field (so only the second and third document would be returned). For the second query, it should find all documents without 'b' in the labels
field and 'h' in the tags
field.
I've found that MongoDB's $not
operator doesn't provide a straight-forward way to negate logical operations as needed. Ideally, I'd like to achieve something like this:
{
$not: {
$and: [
{ labels: a},
{ labels: b},
]
}
}
or
{
$not: {
$and: [
{ labels: b},
{ tags: h},
]
}
}
If there is another operator that can help accomplish this, please let me know. Ultimately, I'm looking for a solution that allows building complex compound queries inside parentheses and easily negating them if there's a NOT
.
EDIT: Added more data to the dataset and further clarified my specific requirements for a solution.