我有一个Tag
架构:
const TagSchema = new Schema({
label: {type: String, unique: true, minlength: 2},
updatedAt: {type: Date, default: null},
createdAt: {type: Date, default: new Date(), required: true},
createdBy: {type: mongoose.Schema.Types.ObjectId, ref: 'Account', default: null}
});
const Tag = mongoose.model('Tag', TagSchema);
然后我有一个Page
架构:
const PageSchema = new Schema({
tags: {type: [{type: mongoose.Schema.Types.ObjectId, ref: 'Tag'}], default: [], maxlength: 5}
});
const Page = mongoose.model('Page', PageSchema);
如您所见,它的Tag
数组中包含tags
引用。
现在我需要做的是当我通过/tags
获取所有标签时,我还需要计算每个标签在所有Page
中使用的次数。
因此,如果Tag
在所有2
中使用Page
次,则应在返回的标记上设置.occurrences
属性。例如,这将是来自/tags
的回复:
[
{_id: '192398dsf7asdsdds8f7d', label: 'tag 1', updatedAt: '20170102', createdAt: '20170101', createdBy: '01238198dsad8s7d78ad7', occurrences: 2},
{_id: '19239asdasd8dsf7ds8f7d', label: 'tag 2', updatedAt: '20170102', createdAt: '20170101', createdBy: '01238198dsad8s7d78ad7', occurrences: 1},
{_id: '192398dsf7zxccxads8f7d', label: 'tag 1', updatedAt: '20170102', createdAt: '20170101', createdBy: '01238198dsad8s7d78ad7', occurrences: 5},
]
我会想象我可以在像这样的mongoose pre('find')
钩子中轻松实现这一点:
TagSchema.pre('find', function() {
Page.count({tags: this._id}, (err, total) => {
this.occurrences = total;
});
});
然而,这里有两个问题:
Page.count
发出错误声称它不是一个功能,我不明白为什么,因为我在其他地方使用它完全没问题。 Page
已正确导入。建议您不能在钩子或类似的东西中使用count
。
this
不是Tag
文件。
所以我想我这样做的方式是完全错误的。
由于我是MongoDB的新手,也许有人可以为我提供更好,更有效的解决方案吗?
答案 0 :(得分:1)
db.Page.aggregate([
{
$unwind:"$tags"
},
{
$group:{
_id:"$tags",
occurrences:{$sum:1}
}
},
{
$lookup:{ //get data for each tag
from:"tags",
localField:"_id",
foreignField:"_id",
as:"tagsData"
}
},
{
$project:{
tagData:{$arrayElemAt: [ "$tagsData", 0 ]},
occurrences:1
}
}
{
$addFields:{
"tagData._id":"$_id",
"tagData.occurrences":"$occurrences"
}
},
{
$replaceRoot: { newRoot: "$tagData" }
}
])
答案 1 :(得分:0)
好的,首先,您需要getQuery(),这样您就可以访问找到tag
的属性了。因此,如果您按_id
找到该标记,则pre
this.getQuery()._id
挂钩中访问该标记
其次,你将需要使用" Parallel"中间件,可以在docs中找到。这允许find方法等到调用done
函数,因此它将等到标记使用新的出现次数更新。
由于无法在pre
挂钩中访问该对象,因此尚未找到它,您将不得不在findOneAndUpdate
挂钩中使用pre
方法。
因此代码应如下所示:
find
方法:
Tag.find({ _id: "foo"}, function (err, foundTag) {
console.log(foundTag)
})
pre
挂钩:
TagSchema.pre('find', true, function (next, done) {
mongoose.models['Page'].count({ tags: this.getQuery()._id }, (err, total) => {
mongoose.models['Tag'].findOneAndUpdate({ _id: this.getQuery()._id }, { occurrences: total }, function () {
next()
done()
})
});
});