I would like to get only those subdocuments from my two object arrays file_history
and uploaded_files
which meet a criteira. Even though I've found this stackoverflow answer #2 (Mongoose - finding subdocuments by criteria) it doesn't work as desired for me or I am missing something.
var projectId = req.params.projectId
var uploadId = req.body.uploadId
let populateQuery = [
{path: 'owner'},
{path: 'uploaded_files.file', match: {upload_id: uploadId}},
{path: 'file_history.file', match: {upload_id: uploadId}}
]
Project.findOne({ project_id: projectId }).populate(populateQuery).then(project => {
console.log(project)
})
My document looks like this:
{
"_id" : ObjectId("5935a41f12f3fac949a5f925"),
"project_id" : 13,
"updated_at" : ISODate("2017-07-05T21:45:46.754Z"),
"created_at" : ISODate("2017-06-05T18:34:07.150Z"),
"owner" : ObjectId("591eea4439e1ce33b47e73c3"),
"name" : "RDemo project",
"uploaded_files" : [
{
"display_name" : "Log_28-6-2017_14-17-53-562.txt",
"file" : ObjectId("595c4c4f3ae2470700ea07e2"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : ISODate("2017-07-05T02:17:51.000Z")
},
{
"display_name" : "Coon.png",
"file" : ObjectId("595c4c553ae2470700ea07e4"),
"upload_id" : ObjectId("595c4c553ae2470700ea07e5"),
"created_at" : ISODate("2017-07-05T02:17:57.000Z")
}
],
"file_history" : [
{
"display_name" : "account working.txt",
"file" : ObjectId("595c0f7ea1d20247285be5f4"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : ISODate("2017-07-04T21:58:22.000Z")
},
{
"display_name" : "Log_28-6-2017_14-17-53-562.txt",
"file" : ObjectId("595c4c4f3ae2470700ea07e2"),
"upload_id" : ObjectId("595c0f7ea1d20247285be5f5"),
"created_at" : ISODate("2017-07-05T02:17:51.000Z")
}
]
}
It will print the project with all it's subdocuments in file_history
and uploaded_files
. However I only want to get those subdocuments which match the given upload_id. What am I doing wrong?
Edit: This question refers to solving it using mongoose. I wasn't able to use the aggregate statement from this question (Retrieve only the queried element in an object array in MongoDB collection) in Mongoose as it returned an empty array, however I was able to run it via MongoDB and it returned indeed the desired result. That's the code I've tried:
let projectId = req.params.projectId // Project ID is an integer and no objectId
let uploadId = new mongoose.Types.ObjectId(req.body.uploadId)
console.log(`ProjectID: ${projectId}, uploadId: ${uploadId}, params: ${req.body.uploadId}`)
let populateQuery = [
{path: 'owner'},
{path: 'uploaded_files.file'},
{path: 'file_history.file'}
]
Project.aggregate(
{$match: {"project_id": projectId}},
{$project: {
uploaded_files: {$filter: {
input: '$uploaded_files',
as: 'uploadedFile',
cond: {$eq: ['$$uploadedFile.upload_id', uploadId]}
}}
}
}
).then(project => {
console.log(project)
})
console.log returns: ProjectID: 13, uploadId: 595c0f7ea1d20247285be5f5, params: 595c0f7ea1d20247285be5f5
which is correct (ids are existent)