-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Populating virtual count field returns the sum of all referencing documents. v5.13.0 #11307
Comments
So what you're saying is if there are 4 reports in the array and each report has 3 reports, it should return 12? |
Yes, it should. It works well for the first case |
So after attempting to reproduce this error, I'm a bit confused as to how you would expect the number 12. const mongoose = require('mongoose');
const ReportSchema = new mongoose.Schema({
reason: {
type: String,
trim: true,
enum: [
'BULLYING',
'FAKE NEWS',
'RACISM',
'SCAM',
'SEXIST',
'SEXUALLY INNAPROPRIATE',
'SPAM',
'OTHER',
],
},
description: {
type: String,
trim: true,
required: false,
maxLength: 280,
},
createdAt: {
type: Date,
default: Date.now,
},
reportType: {
type: String,
enum: ['Post', 'Comment'],
required: true,
},
reportModel: {
type: mongoose.Schema.Types.ObjectId,
refPath: 'reportType',
required: true,
},
});
const CommentSchema = new mongoose.Schema(
{
content: {
type: String,
trim: true,
maxLength: 2048,
},
createdAt: {
type: Date,
default: Date.now,
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: false,
},
],
numberOfLikes: {
type: Number,
default: 0,
},
comment: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
required: false,
},
replies: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
required: false,
},
],
isReply: {
type: Boolean,
default: false,
},
isChannelComment: {
type: Boolean,
default: false,
},
edited: {
type: Boolean,
default: false,
},
deleted: {
type: Boolean,
default: false,
},
deletedAt: {
type: Date,
required: false,
},
space: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Space',
required: false,
},
trendingCount: {
type: Number,
default: 0,
min: 0,
},
},
{ toJSON: { virtuals: true }, toObject: { virtuals: true } }
);
CommentSchema.virtual('reportCount', {
ref: 'Report',
localField: '_id',
foreignField: 'reportModel',
justOne: false,
count: true,
});
// TODO: fix reportReplyCount
CommentSchema.virtual('reportReplyCount', {
ref: 'Report',
localField: 'replies',
foreignField: 'reportModel',
justOne: false,
count: true,
options: {
match: {
reportType: 'Comment',
},
},
});
const Comment = mongoose.model('Comment', CommentSchema);
const Report = mongoose.model('Report', ReportSchema);
async function run() {
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();
const comment = await Comment.create({
content: 'Spamming Spamerson'
});
const otherComment = await Comment.create({
content: 'Spamming Springsteen'
});
const differentComment = await Comment.create({
content: 'Spamming Sanderson'
});
const finalComment = await Comment.create({
content: 'Spamming Sam'
});
const report = await Report.create({
reason: 'SPAM',
reportType: 'Comment',
reportModel: comment._id
});
const secondReport = await Report.create({
reason: 'SPAM',
reportType: 'Comment',
reportModel: comment._id
});
const thirdReport = await Report.create({
reason: 'SPAM',
reportType: 'Comment',
reportModel: comment._id
});
await Comment.findOneAndUpdate({_id: comment._id}, {replies: [otherComment._id, finalComment._id, differentComment._id]});
await Comment.findOneAndUpdate({_id: otherComment._id}, {replies: [comment._id, finalComment._id, differentComment._id]})
await Comment.findOneAndUpdate({_id: finalComment._id}, {replies: [otherComment._id, finalComment._id, differentComment._id]})
const test = await Comment.findOne({_id: comment._id}).populate('reportReplyCount').populate('reportCount');
console.log(test);
}
run(); |
You're right that const mongoose = require('mongoose');
mongoose.set('debug', true);
const ReportSchema = new mongoose.Schema({
reason: {
type: String,
trim: true,
enum: [
'BULLYING',
'FAKE NEWS',
'RACISM',
'SCAM',
'SEXIST',
'SEXUALLY INNAPROPRIATE',
'SPAM',
'OTHER',
],
},
description: {
type: String,
trim: true,
required: false,
maxLength: 280,
},
createdAt: {
type: Date,
default: Date.now,
},
reportType: {
type: String,
enum: ['Post', 'Comment'],
required: true,
},
reportModel: {
type: mongoose.Schema.Types.ObjectId,
refPath: 'reportType',
required: true,
},
});
const CommentSchema = new mongoose.Schema(
{
content: {
type: String,
trim: true,
maxLength: 2048,
},
createdAt: {
type: Date,
default: Date.now,
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: false,
},
],
numberOfLikes: {
type: Number,
default: 0,
},
comment: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
required: false,
},
replies: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
required: false,
},
],
},
{ toJSON: { virtuals: true }, toObject: { virtuals: true } }
);
CommentSchema.virtual('reportCount', {
ref: 'Report',
localField: '_id',
foreignField: 'reportModel',
justOne: false,
count: true,
});
// TODO: fix reportReplyCount
CommentSchema.virtual('reportReplyCount', {
ref: 'Report',
localField: 'replies',
foreignField: 'reportModel',
justOne: false,
count: true,
options: {
match: {
reportType: 'Comment',
},
},
});
const Comment = mongoose.model('Comment', CommentSchema);
const Report = mongoose.model('Report', ReportSchema);
async function run() {
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();
const comment = await Comment.create({
content: 'Spamming Spamerson'
});
const otherComment = await Comment.create({
content: 'Spamming Springsteen'
});
const differentComment = await Comment.create({
content: 'Spamming Sanderson'
});
const finalComment = await Comment.create({
content: 'Spamming Sam'
});
const report = await Report.create({
reason: 'SPAM',
reportType: 'Comment',
reportModel: comment._id
});
const secondReport = await Report.create({
reason: 'SPAM',
reportType: 'Comment',
reportModel: comment._id
});
const thirdReport = await Report.create({
reason: 'SPAM',
reportType: 'Post',
reportModel: new mongoose.Types.ObjectId()
});
await Comment.findOneAndUpdate({_id: comment._id}, {replies: [otherComment._id, finalComment._id, differentComment._id, comment._id]});
await Comment.findOneAndUpdate({_id: otherComment._id}, {replies: [comment._id, finalComment._id, differentComment._id]})
await Comment.findOneAndUpdate({_id: finalComment._id}, {replies: [otherComment._id, finalComment._id, differentComment._id]})
const test = await Comment.findOne({_id: comment._id}).populate('reportReplyCount');
console.log(test.reportReplyCount); // [0, 0, 0, 2]
}
run(); If you want to sum up CommentSchema.virtual('reportReplyCount', {
ref: 'Report',
localField: 'replies',
foreignField: 'reportModel',
justOne: false,
count: true,
options: {
match: {
reportType: 'Comment',
},
},
}).get(arr => Array.isArray(arr) ? arr.reduce((sum, el) => sum + el, 0) : 0); Is there anything blocking you from upgrading to Mongoose 6? |
I have Comment and Report models. Comments can have multiple replies stored in field replies which is array of references.
When User reports the comment/reply new Report document is stored in Report collection with reference to the Comment.
I have 2 virtuals in Comment schema, reportCount (number of reports for that comment) and reportReplyCount (number of reports for comment replies).
The reportCount works fine, returns the number of reports for that Comment. But the reportReplyCount does not. It returns total number of references in the reference array (replies) instead of number of reports for those referenced replies. Version of mongoose is 5.13.0. That means if I have 4 replies in that replies array it will return number 4. But it should return sum of all reports for those references.
Comment Schema
Report Schema
The text was updated successfully, but these errors were encountered: