Reputation: 28328
Currently I have this function which retrieves all Tag
documents used in all Page
documents and counts the number of occurrences
and attached them to each Tag
document returned:
exports.getAll = (req, res, next) => {
const config = utils.prepareOptions(req.query);
async.waterfall([
(done) => {
Tag.count({}).exec((err, total) => {
return done(err, total);
});
}
], (err, total) => {
Page.aggregate([
// {
// $unwind: "$tags"
// },
{
$group: {
_id: "$tags",
occurrences: {
$sum: 1
}
}
},
{
$lookup: {
from: "tags",
localField: "_id", // this is supposely wrong but I can't prove it
foreignField: "_id",
as: "tagsData"
}
},
{
$unwind: "$tagsData"
},
{
$match: {
"tagsData.label": new RegExp(config.query, 'i')
}
},
{
$project: {
occurrences: "$occurrences",
tagData: '$tagsData'
}
},
{
$addFields: {
"tagData._id": "$_id",
"tagData.occurrences": "$occurrences"
}
},
{
$replaceRoot: {
newRoot: "$tagData"
}
},
{$sort: {[config.sortBy]: config.order}},
{$limit: config.limit},
{$skip: config.offset}
], (err, tags) => {
console.log(tags);
console.log(err);
console.log(total);
if (err) {
return next(err);
}
res.json({
error: null,
data: tags,
total: total,
results: tags.length
});
});
});
};
The problem with this is that a Tag
doesn't necessarily have to be used with a Page
at any given time. This results in a problem when calling this function because the Tag
s that aren't used are not returned.
So what I need to do is to also include every Tag
that isn't used and set an occurrences: 0
on them.
So if I have 3 Tag
documents:
[
{_id: 1203f8sad9sf, label: 'Tag 1'},
{_id: 1203asdf89sf, label: 'Tag 2'},
{_id: 1203asqw89sf, label: 'Tag 3'}
]
And a Page
document:
{
_id: 90182312,
tags: [ObjectId(1203f8sad9sf), Object(1203asdf89sf)]
}
And Tag 1
and Tag 2
are part of the Page
's tags
array, how do I also return Tag 3
so that it is included in the tags
that is returned from the aggregate
method?
Upvotes: 0
Views: 31
Reputation: 10918
Given I understand your intention correctly and also assuming that you've got some code in place to make sure that there are no duplicate tag IDs in a page's tags
field this query can be rewritten in a substantially more efficient and concise way:
db.getCollection('tags').aggregate([{
$lookup: {
from: "page",
localField: "_id",
foreignField: "tags",
as: "pageData"
}
}, {
$addFields: {
"occurrences": {
$size: "$pageData"
}
}
}])
Upvotes: 1