Reputation: 1388
I have a user model schema, a work model schema, and a critique model schema. The relationship between these schema's is a user can submit many works (like blog posts), and can comment/review (which we call critiques) other people's posts (works).
So when a user submits a critique (think of it like a review), this is my post route. I find the work by the id, then create a new critique model object, and pass that to the .create() mongoose function. All goes seemingly well until I hit the foundWork.critiques.push(createdCritique)
line. the console log errors out saying:
BulkWriteError: E11000 duplicate key error collection: zapper.critiques index: username_1 dup key: { : null }
Obviously, it is saying that there are two username keys in the objects and they're conflicting with each other, but I'm not familiar enough with this to find the root of the issue and fix it in the mongoose models. The models are below. If anyone could help, that'd be greatly appreciated.
// post route for getting the review
router.post('/:id', isLoggedIn, function(req, res) {
Work.findById(req.params.id, function(err, foundWork) {
if (err) {
console.log(err);
} else {
// create a new critique
var newCritique = new Critique ({
reviewerName: {
id: req.user._id,
username: req.user.username
},
work: {
id: foundWork._id,
title: foundWork.title
},
critique : req.body.critique,
date: Date.now(),
rating: 0
});
// save new critique to db
Critique.create(newCritique, function(err, createdCritique) {
if (err) {
console.log(err)
} else {
console.log("Created critique is ");
console.log(createdCritique);
// push the new critique into array of critiques of the work
foundWork.critiques.push(createdCritique);
// save to db
foundWork.save();
}
});
}
});
User model:
var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');
var UserSchema = new mongoose.Schema({
firstname: String,
lastname: String,
username: String,
password: String,
email: String,
zip: String,
bio: {
type: String,
default: ''
},
influences: {
type: String,
default: ''
},
favBooks: {
type: String,
default: ''
},
notWriting: {
type: String,
default: ''
},
favHero: {
type: String,
default: ''
},
favVillain: {
type: String,
default: ''
},
works: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Work'
}
],
critiques: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Critique'
}
],
friends: [
{
friendId: String,
friendName : String,
friendPic: String
}
],
friendRequests: [
{
sendingFriendId: String,
sendingFriendName : String,
sendingFriendPic: String
}
],
createdDate: {
type: Date,
default: Date.now
},
lastLogin: {
type: Date,
default: Date.now
}
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
Work model:
var mongoose = require('mongoose');
var WorkSchema = new mongoose.Schema({
title: String,
genre: String,
workType: String,
length: Number,
ageRange: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
manuscriptText: String,
critiques: [
{
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Critique"
}
}
],
ratingNumber: [Number],
ratingSum: {
type: Number,
default: 0
},
date: {
type: Date,
default: Date.now
},
isPublic: {
type: Boolean,
default: true
}
});
module.exports = mongoose.model("Work", WorkSchema);
Critique model:
var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');
var CritiqueSchema = new mongoose.Schema({
reviewerName: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
work: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Work"
},
title: String
},
critique: String,
date: {
type: Date,
default: Date.now
},
rating: [Number]
});
CritiqueSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("Critique", CritiqueSchema);
Upvotes: 1
Views: 11813
Reputation: 1679
When you create a unique index in MongoDB, the default behavior is that it will index null values also.
This means if you have a document in your collection with a username of null, you can not add another one with a username of null.
What you need is a sparse index which only indexes actual values (and ignores documents with null for that field).
Check this link It shows how to create a sparse index vs "normal" one in mongoose (index: true, vs spare: true). Most of the time you would want sparse indexes.
Upvotes: 5