Consider a collection of documents that collects scores as an array of nested documents, like this (I'm using MongoDb 4.2):
{
"scores" : [
{ "value" : 2 },
{ "value" : 3 },
{ "value" : 4 }
]
}, {
"scores" : [
{ "value" : 8 },
{ "value" : 9 },
{ "value" : 10 }
]
}, {
"scores" : [
{ "value" : 7 },
{ "value" : 7 },
{ "value" : 10 }
]
}
Consider now the following use case: "Give me all the documents that contains ONLY scores in the range [X, Y]". Said differently, please filter out the documents that have at least one value that is NOT in the range [X-Y]. Side note: in the actual data, the scores are real numbers, so doing some $in queries won't help here.
Let's consider three ranges:
- Range [8, 10] (one documents should match)
- Range [0, 1] (0 document matching).
- Range [5, 6] (0 document matching).
As a non-expert yet in mongo, my first try was to do this:
db.test.find({
$and: [
{ "scores.value": {$gte: 8}},
{ "scores.value": {$lte: 10}}
]
})
- Case [8, 10]: 2 records.
- Case [0, 1] : 0 records
- Case [5, 6] : 2 records
So there are some odd stuff here: first results suggests that my query actually returns scores with either of the condition satisfied (somewhat an $or instead of $and). But is that were true, I would have retrieved all records on the second case [0, 1] instead of 0. Obviously something I'm using the wrong way here, but if someone can explain me why, I'd be very happy.
Next query:
db.test.find({
"scores": {
$elemMatch: {
value: {$gte: 6.5, $lte: 6.8}
}
}
})
- Case [8, 10]: 2 records.
- Case [0, 1] : 0 records
- Case [5, 6] : 0 records
For that one, everything is fine and works as documented / expected, but it does not answer my original use case.
So beside understanding what happened using the first query, does anyone knows a way to achieve what I'm trying to do ?