如何计算ObjectId数组中ObjectId事件的数量“并将结果附加到每个正在返回的文档?

我有一个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); 

正如你可以看到它的tags数组中包含一个Tag引用。

现在我需要做的是当我通过/tags获取所有标签,我还需要统计每个标签在所有Page使用的次数。

所以如果一个Tag在所有Page使用了2次,它应该在返回的标签上设置一个.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}, ] 

我会想象,我可以很容易地在这样一个mongoosepre('find')钩子中实现这个:

 TagSchema.pre('find', function() { Page.count({tags: this._id}, (err, total) => { this.occurrences = total; }); }); 

但是,这里有两个问题:

  • Page.count抛出一个错误,说它不是一个函数,我不明白为什么,因为我用它在别的地方很好。 Page已正确导入。 build议你不能在钩子或类似的东西中使用count

  • this不是Tag文件。

所以我想我正在做的这个方式是完全错误的。

由于我是MongoDB的新手,也许有人可以为我的问题提供一个更好的工作解决scheme?

 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" } } ]) 

首先,你需要getQuery()这允许你访问你正在寻找tag的属性。 所以如果你通过_idfind标签,你可以通过this.getQuery()._id

其次,您将需要使用“并行”中间件,可以在文档中find。 这允许find方法等待,直到done函数被调用,所以它将等待,直到标签更新为新的事件编号。

由于对象不能在pre钩子中访问,因为它还没有被发现,所以你必须在pre钩子中使用findOneAndUpdate方法。

所以代码应该是这样的:

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() }) }); });