I'm trying to learn mongodb, my database looks like this:
{
"_id" : ObjectId("625c95836be34e3c73c37316"),
"cuisine" : "Chinese",
"grades" : [
{
"date" : ISODate("2014-02-25T00:00:00Z"),
"grade" : "A",
"score" : 112
},
{
"date" : ISODate("2013-08-14T00:00:00Z"),
"grade" : "C",
"score" : 28
},
{
"date" : ISODate("2012-07-18T00:00:00Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2012-03-09T00:00:00Z"),
"grade" : "A",
"score" : 13
},
{
"date" : ISODate("2011-10-27T00:00:00Z"),
"grade" : "A",
"score" : 12
},
{
"date" : ISODate("2011-05-19T00:00:00Z"),
"grade" : "A",
"score" : 13
}
],
"name" : "janette"
},
{
"_id" : ObjectId("625c95836be34e3c73c37317"),
"cuisine" : "Chinese",
"grades" : [
{
"date" : ISODate("2014-01-07T00:00:00Z"),
"grade" : "A",
"score" : 17
},
{
"date" : ISODate("2013-05-09T00:00:00Z"),
"grade" : "B",
"score" : 107
}
],
"name" : "Annie'S Kitchen"
}
each object has an array that owns the same fields. If I try:
db.restaurants.find({"grades.score":{ $gt: 80, $lt: 100 }});
it will catch both but should catch none. Also I want to be able to check:
db.restaurants.find("grades.score":{$gt: 70},"grades.grade":{/^A$/} });
I need to check the fields only with the fields in the same position on the array.
I don't know how to explain it better, sorry, and thanks for the help.
CodePudding user response:
You can use $map
to project an auxiliary boolean array and use $allElementsTrue
or $anyElementTrue
to filter it.
db.restaurants.aggregate([
{
"$match": {
$expr: {
"$allElementsTrue": {
"$map": {
"input": "$grades",
"as": "g",
"in": {
$and: [
{
$gt: [
"$$g.score",
80
]
},
{
$lt: [
"$$g.score",
100
]
}
]
}
}
}
}
}
}
])
Here are the Mongo playgrounds for your first and second query.