I'm fighting with redact right now and I'm not sure to understand it.
I just read the docs and tried to use redact on a collection grades (it comes from mongodb online training)
A document in the collection "grades" looks like this :
{
"_id" : ObjectId("50b59cd75bed76f46522c34e"),
"student_id" : 0,
"class_id" : 2,
"scores" : [
{
"type" : "exam",
"score" : 57.92947112575566
},
{
"type" : "quiz",
"score" : 21.24542588206755
},
{
"type" : "homework",
"score" : 68.19567810587429
},
{
"type" : "homework",
"score" : 67.95019716560351
},
{
"type" : "homework",
"score" : 18.81037253352722
}
]
}
I use the following query :
db.grades.aggregate([
{ $match: { student_id: 0 } },
{
$redact: {
$cond: {
if: { $eq: [ "$type" , "exam" ] },
then: "$$PRUNE",
else: "$$DESCEND"
}
}
}
] );
With this query, each type an exam is found, this sub document should be excluded. And it works, the result is:
{
"_id" : ObjectId("50b59cd75bed76f46522c34e"),
"student_id" : 0,
"class_id" : 2,
"scores" : [
{
"type" : "quiz",
"score" : 21.24542588206755
},
{
"type" : "homework",
"score" : 68.19567810587429
},
{
"type" : "homework",
"score" : 67.95019716560351
},
{
"type" : "homework",
"score" : 18.81037253352722
}
]
}
but if I invert the condition, I expect that only exams are kept in the result :
if: { $eq: [ "$type" , "exam" ] },
then: "$$DESCEND",
else: "$$PRUNE"
however the result is empty.
I don't understand why subdocument of type "exam" are not included.
$redact. Restricts the contents of the documents based on information stored in the documents themselves.
On large collections of millions of documents, MongoDB's aggregation was shown to be much worse than Elasticsearch. Performance worsens with collection size when MongoDB starts using the disk due to limited system RAM. The $lookup stage used without indexes can be very slow.
The $redact
stage starts at the root document and its fields, and only when that document fulfills the condition to $$DESCEND
, it examines the sub-documents included in that document. That means the first thing $redact does with your document is examine this:
{
"_id" : ObjectId("50b59cd75bed76f46522c34e"),
"student_id" : 0,
"class_id" : 2,
"scores" : [] // Some array. I will look at this later.
}
It doesn't even find a type
field here, so $eq: [ "$type" , "exam" ]
is false. What did you tell $redact to do when the condition is false? else: "$$PRUNE"
, so the whole document is pruned before the sub-documents are examined.
As a workaround, test if $type
is either "exam"
or doesn't exist. You didn't explicitly ask for a working solution, so I will leave it as an exercise to you to figure out how to do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With