Reputation: 3488
I'm using mongoDB through mongoose in a node.js application.
In my db I have this general format:
Books:
BookSchema = {
variousData,
//Books contain pages
pages: [{type: pageSchema}]
}
Pages:
pageSchema = {
variousData,
//Pages contain frames
frames: [frameSchema]
}
Frames:
frameSchema = {
variousData
}
I want to write a count query that will count the total number of frames in all pages in all books.
So if I have this content in my db:
Book1 = {
data:data,
pages: [
{data:data,
frames: [frame1,frame2,frame3]
},
{data:data,
frames: [frame1,frame2,frame3]
},
{data:data,
frames: [frame1,frame2,frame3]
}
]
}
and
Book2 = {
data:data,
pages: [
{data:data,
frames: [frame1,frame2]
},
{data:data,
frames: [frame1,frame2]
},
{data:data,
frames: [frame1,frame2]
}
]
}
I'm expecting to get an end result of 15 (9 frames in book 1 and 6 frames in book 2)
All my attempts ended up with errors.
I can write a loop, but I feel like mongoose would have a better alternative.
Any suggestions?
Thanks all!
Upvotes: 2
Views: 2054
Reputation: 50406
The most efficient way would be like this:
Book.aggregate([
{ "$project": {
"pages": {
"$map": {
"input": "$pages",
"as": "page",
"in": { "$size": "$$page.frames" }
}}
}},
{ "$unwind": "$pages" },
{ "$group": {
"_id": null,
"pages": { "$sum": "$pages" }
}}
],function(err,results) {
})
Basically there the $map
operator allows you to traverse the elements of the "pages" array, take a look at each "frames" array and return the $size
. Now the content of "pages" is just an array of sizes for each "frames", and therefore the count.
Then all you really need to do is "add" those together. So you $unwind
the array and $sum
all the page counts for each frame together with a $group
.
Upvotes: 2