I’m new to MongoDB, so I may have some terminology wrong, but I don’t think I’ve seen anyone ask a question exactly like this:
If I have a collection of documents that have a shape something like:
{
_id: ObjectID('656ce741b78f8f5fea229c4f'),
year: 2,
name: "Student Name",
grades: [
{
date: ISODate('2014-08-16T00:00:00.000Z'),
grade: 'A',
score: 97
},
{
date: ISODate('2014-03-19T00:00:00.000Z'),
grade: 'A',
score: 91
},
{
date: ISODate('2015-08-16T00:00:00.000Z'),
grade: 'B',
score: 82
}
]
}
How would I find all of the straight A students? That is, all of the students such that the grades array only contains grades.grade = "A"
. I can provide the actual document structure, but the logic should be the same for this example collection of imaginary student documents.
I’ve tried using $all
, but I think that expects an array of values, not an array of objects. I’ve also tried $elemMatch
with $ne: B
and $ne: C
, but that seems to return anything where at least one of the elements is an A
, instead of requiring all elements to be A
.
2
Answers
The following query should only match documents where all elements of the grades array have a value that is not equal B or C:
{"grades.grade":{$nin: ["C","B"]}}
Instead of enumerating all the negative possibilities (i.e.the values that you don’t want, currently
B
andC
), you can use$map
to create a boolean array that check forgrades.grade
equal to A or not. Then, use$allElementsTrue
on the resulting array to check whether all array entries are A or not. In this way, if you are introducing new negative values likeD
orE
…, you code is still working as expected.Mongo Playground