node.js mongodb one-to-many association error - node.js

I got a One-to-Many association error between(user 1<--->1..*robot) , I want to add a new document when a new user subscribe he should add a new robot with (reference and nom), so the user information should be add on the user collection as new document and the robot information should be add as a new collection on the robot collection in my mongodb database.
/routes/users.js :
router.post('/register', function(req, res, next) {
//tester si username exist
var user = new models.user({
nom_prenom: req.body.nom_prenom,
username: req.body.username,
password: req.body.password,
email: req.body.email,
sexe: req.body.sexe,
adresse: req.body.adresse,
admin: false
});
var robot = new models.robot({
reference: req.body.reference,
nom: req.body.nom,
flag: req.body.flag
});
user.save(function(err, u){
if(err) res.json(err);
res.json(u);
})
robot.save(function(err, u){
if(err) res.json(err);
res.json(u);
})
});
/models/users.js :
var mongoose = require('../config/db');
var UserSchema = mongoose.Schema({
nom_prenom: String,
password: String,
username: String,
email: String,
//username: { String, unique:true, required:true },
//email: { String, unique:true, required:true },
date_naissance: Date,
adresse: String,
sexe: String,
equipements:[{type: mongoose.Schema.Types.ObjectId, ref: 'Equipement'}],
robots:[{type: mongoose.Schema.Types.ObjectId, ref: 'Robot'}],
admin: Boolean
});
module.exports = mongoose.model('User', UserSchema);
/models/robot :
var mongoose = require('../config/db');
var RobotSchema = mongoose.Schema({
reference: String,
nom: String,
flag: Boolean,
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
});
module.exports = mongoose.model('Robot', RobotSchema);
/routes/robots.js:
router.get('/', function(req, res, next){
models.robot.aggregate([
{
"$group": {
"_id": "$user_id",
"robots": { "$push": "$$ROOT" }
}
}
]).exec(function(err, results){
if (err) res.json({error: err});
models.user.populate(results, { "path": "_id" }, function(err, result) {
if(err) res.json({error: err});
console.log(result);
res.json(result);
});
});
});
the result Postman:
The Result on CMD after i execute :db.robots.find().pretty();
{
"_id" : ObjectId("57b5862673c11c840b31cc55"),
"reference" : "Rob9999",
"nom" : "Robot 9999",
"flag" : false,
"__v" : 0
}
and the result on CMD after I execute db.users.find().pretty();
{
"_id" : ObjectId("57b5862673c11c840b31cc54"),
"nom_prenom" : "test",
"username" : "test",
"password" : "test",
"email" : "test#orange.tn",
"sexe" : "femme",
"adresse" : "tunis",
"admin" : false,
"robots" : [ ],
"equipements" : [ ],
"__v" : 0
}
I don't find why the array robots in user is empty??
Can I do that insert a user and a robot that should appear in the list of robots of that user?

I think you didn't push newly created robot's _id to the robots array in user document while saving it.
Try This:
router.post('/register', function(req, res, next) {
//tester si username exist
var user = new models.user({
nom_prenom: req.body.nom_prenom,
username: req.body.username,
password: req.body.password,
email: req.body.email,
sexe: req.body.sexe,
adresse: req.body.adresse,
admin: false
});
var robot = new models.robot({
reference: req.body.reference,
nom: req.body.nom,
flag: req.body.flag
});
// dont change the header(res.json(u)) multiple times, make sure you set the header
// single time only. otherwise you may get unnecessary errors.
robot.save(function(err, u){
if(err) res.json(err);
//save user only after robot is successfully saved and push its id into robots array.
user.robots.push(u._id);
user.save(function(err, user){
if(err) res.json(err);
res.json(user);
return;
});
});
});

Related

How to use mongoose to create a student that's managed by a parent

Edit #2: Working code
This does what I want it to do now:
// route
app.post("/users/:id/createStudent", function(req, res){
Student.create(function(err){
if(err){
console.log(err)
res.redirect("/")
} else {
const newStudent = new Student({
firstName: req.body.firstName,
lastName: req.body.lastName,
age: req.body.age,
instrument: req.body.instrument,
});
newStudent.save()
.then(() => Parent.findById(req.params.id))
.then((parent) => {
parent.students.push(newStudent);
return parent.save();
});
req.flash("success", "Successfully Created Student");
res.redirect("/users/:id");
}
})
});
// parent model
const mongoose = require("mongoose"),
Schema = mongoose.Schema,
passportLocalMongoose = require("passport-local-mongoose");
const ParentSchema= new Schema({
username: String,
lastName: String,
email: String,
password: String,
students: [],
});
ParentSchema.plugin(passportLocalMongoose);
const Parent = mongoose.model("parent", ParentSchema);
module.exports = Parent;
Brand new developer here. I'm trying to build an app where a parent user can create a student user and a teacher user can assign said student weekly tasks. I'm having trouble with the create student route. I'm not sure how to get the student object to store the parent's id properly. I've been trying to find a solution for a few days now and can't seem to find anything that deals with this specifically and the docs haven't helped either. I hope I'm just missing something and one of you kind folks can at least point me in the right direction.
Here's my code:
//parent model
const mongoose = require("mongoose"),
passportLocalMongoose = require("passport-local-mongoose");
const parentSchema= new mongoose.Schema({
username: String,
lastName: String,
email: String,
password: String,
student: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Student"
},
username: String,
}
});
parentSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("Parent", parentSchema);
// student model
const mongoose = require("mongoose");
const studentSchema = new mongoose.Schema({
firstName: String,
lastName: String,
age: String,
instrument: String,
parent: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Parent"
},
username: String
},
});
module.exports = mongoose.model("Student", studentSchema);
// create student route
app.post("/users/:id/createStudent", function(req, res){
const newStudent = new Student({
firstName: req.body.firstName,
lastName: req.body.lastName,
age: req.body.age,
instrument: req.body.instrument,
parent: {
_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Parent"
},
username: String
},
});
Parent.findById(req.params.id, function(err, foundParent){
if(err){
req.flash("error", "Something went wrong");
console.log(err);
res.redirect("/users/:id");
} else {
const parent = foundParent
Student.create(newStudent, parent, function(err, student){
if(err){
console.log(err);
} else {
student.parent.id = req.parent._id;
student.parent.username = req.parent.username;
student.save();
parent.student.push(newStudent);
parent.save();
req.flash("success", "Successfully Created Comment");
res.redirect("/users/" + parent._id);
}
})
}
});
});
In the mongo shell, db.students.find() puts out this as my student object after I fill out the form:
db.students.find()
{ "_id" : ObjectId("5f0b33facd6fa70355f14774"), "firstName" : "Johnny", "lastName" : "Apple", "age" : "2014-03-04", "instrument" : "drums", "parent" : { "username" : "function String() { [native code] }" }, "__v" : 0 }
Sorry for the long code. I've just been trying so many things that it's added up to what you see here. Thanks for any advice you might give and for reading this far.
Edit
Updated code:
app.post("/users/:id/createStudent", function(req, res){
Parent.findById(req.params.id, function(err, foundParent){
if(err){
req.flash("error", "Something went wrong");
console.log(err);
res.redirect("/users/:id");
} else {
const newStudent = new Student({
firstName: req.body.firstName,
lastName: req.body.lastName,
age: req.body.age,
instrument: req.body.instrument,
parent: {
id: foundParent,
username: foundParent.username
},
});
Student.create(newStudent, foundParent, function(err, student){
if(err){
console.log(err);
} else {
student.parent._id = foundParent._id;
student.parent.username = foundParent.username;
student.save();
foundParent.student.push(newStudent);
foundParent.save();
req.flash("success", "Successfully Created Student");
res.redirect("/users/" + foundParent._id);
}
})
}
});
});
So the new error this is producing is DocumentNotFoundError: No document found for query "{ _id: 5f0a7026e330500413ee599a }" on model "Student" which I assume is because I don't have populate in there. I'm just not sure where the populate option would fit in?
mongoose.Schema.Types.ObjectId is a type not a value.
Try using mongoose.Schema.Types.ObjectId(req.parent.id)
Edit
Another option to try:
Move the const newStudent = block inside the else block of the findById callback.
Inside the new Student( constructor, use
parent: {
id: foundParent,
username: foundParent.username
}
Because of the schema definition, when you save the document, mongoose should store a DBRef in the student collection, which can then be reconstituted with populate.

How can I insert data of user schema to main schema using mongoose

I am new in this and not getting how to insert child schema data to a parent schema array.:
My child schema model defined as :-
//user model
var userrSchema = new mongoose.Schema({
email : {
type: String,
required: "Email can't be empty.",
// unique: true
},
password: {
type: String,
required: "Password name can't be empty."
},
});
mongoose.model('Userr' , userrSchema);
And I have defined parent (Admin) schema as:-
//define admin schema
var adminSchema = new mongoose.Schema({
companyName : {
type: String,
required: "Company name can't be empty.",
required: false
},
admins: {
_id: mongoose.Schema.Types.ObjectId,
email : {
type: String,
required: "Email can't be empty.",
unique: true
},
password: {
type: String,
required: "Password name can't be empty."
},
users:[ userrSchema ]
}
});
mongoose.model('Admin', adminSchema);
I have defined both in same model file. I have a controller to register parent schema :-
mongoose.model('Admin', adminSchema);
const Admin = mongoose.model('Admin');
var MongoClient = require('mongodb').MongoClient;
module.exports.registerAdmin = (req, res, next) =>{
var admin = new Admin();
admin.companyName = req.body.companyName;
admin.admins = {
email : req.body.email,
password: req.body.password,
users : []
};
admin.save((err, doc) =>{
After registering admin schema from route file :- router.post('/registerAdmin' , ctrlAdmin.registerAdmin) I am getting result as:-
{
"admins": {
"email": "xyz#ing.com",
"password": "$2a$10$juGvica8UTqtmyywnWQuKOo9KpqX9JeFfqy1n6GR4xDL2GMLM0hze",
"users": []
},
"_id": "5cf8b54e66b45740ae68feac",
"companyName": "ABC"
"__v": 0
}
So how will I register child schema and push the details it into the parent schema users key ?? Please help . I am new in this and not getting a single idea how to insert child schema data.
EDIT:- Updated save function with admin auth
Created controller for child schema but after running the url nothing is happening:
module.exports.registerUserr = (req, res, next) =>{
var userr = new Userr();
userr.email = req.body.email,
userr.password = req.body.password,
userr.firstName = req.body.firstName,
userr.lastName = req.body.lastName,
userr.phoneNumber = req.body.phoneNumber,
userr.role = "user",
userr.verified = "false"
userr.save((err, doc) =>{
if(!err){
if(req.userData.role2 === 'admin') {
console.log("saving successful");
res.send(doc);
Admin.findOneAndUpdate({ _id: req.userData.userId },{ admins : { $push: { users: doc }}},
function (error, success) {
if (error) {
console.log(error);
}
console.log(success);
});
}
}
});
and in route router.post('/registerUserr' ,checkAuth, ctrlUserr.registerUserr);
Try replacing the save function with this
userr.save((err, doc) => {
if (!err) {
res.send(doc);
Admin.findOneAndUpdate(
{ _id: req.body.id },
{ admins: { $push: { users: userr }}},
function (error, success) {
if (error) {
console.log(error);
}
console.log(success);
}
});
}
}

Many to one relationships in mongoose. How to access and output the referred to object ID's?

I'm trying to create a "wishlist" feature for users on my node / mongo application. I've assumed the best way to model the scheme would be to reference the items they like. So far my reading has brought me to this point (I'm not very familiar with the Types.ObjectID):
Schema Model
var UserSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
trim: true
},
password: {
type: String,
required: true
},
wishlist: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Wishlist",
required: true
}]
});
I've managed to write some code which pushes the relevant _id into the "Likes" array:
Product.findById(productID).exec(function (err, user) {
User.updateOne({ _id: req.session.userId }, { "$push": { "wishlist": productID } }, function (err, user) {
if (err) {
console.log("Failed to add")
} else {
console.log(productID + " has been added")
}
});
});
This outputs in the database like so:
{
"_id" : ObjectId("5c3f7e1f1268203b1f31cb17"),
"email" : "email",
"password" : "password",
"__v" : 0,
"wishlist" : [
ObjectId("5c41f4b42f82b14798d5c7fc"),
ObjectId("5c41f4b42f82b14798d5c7ff")
]
}
I'm stuck on how I'd output these wishlist items in my template. My assumption was to get the data like this:
router.get('/wishlist', middleware.requiresLogin, function(req, res, next) {
User.findOne({ _id: req.session.userId }, function(err, user) {
res.render('wishlist', {
title: 'Wishlist',
template: 'wishlist',
saved: user.wishlist,
header: true,
footer: true
});
});
});
And the loop through the items like this:
{{#each saved }} Code goes here {{/each }}
Am I approaching this correctly?
you'll need to populate the wishlist field, try this,
User.findOne({ _id: req.session.userId }).
populate('wishlist').
exec(function (err, user) {
res.render('wishlist', {
title: 'Wishlist',
template: 'wishlist',
saved: user.wishlist,
header: true,
footer: true
});
});
You can refer to the Populate (mongoose documentation).
//User_controller.js
exports.getUser = (req, res) => {
User.findOne({ _id: req.session.userId })
.populate('wishlist')
.then((user) => { res.json(user) })
.catch((error) => { res.status(500).json({ error })
});
};
// UserRoute.js
const express = require("express");
const router = express.Router();
const userCtrl = require('./user_controller');
router.get('/:id', userCtrl.getUser);
module.exports = router;
//server.js
//...
const userRoute = require("./UserRoute");
app.use("/user", userRoute);
//...

How to check if an Id exist in mongodb array if not push the Id into the array

am using mongoose for my schema design i want to check a user collection if a device id exist in am array if false push the device into the user devices array
here is ma user schema
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
var deviceSchema = mongoose.Schema(
{
macAddress: {type: String, required: true, unique: true},
createdAt: {type: Date, default: Date.now},
}
)
var Device = mongoose.model('Device', deviceSchema);
module.exports = Device;
here is my user schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = Schema(
{
firstname: {type: String, required: true},
lastname: {type: String, required: true},
email: {type: String, required: true, unique: true},
username: {type: String, required: true, unique: true},
password: {type: String, required: true},
createdAt: {type: Date, default: Date.now},
devices: [{ type: Schema.Types.ObjectId, ref: 'Device1' }]
}
)
var User = mongoose.model('User', userSchema);
module.exports = User;
and here is my nodejs router
router.post('/user/device/:username', function(req, res, next) {
if(!req.body.macAddress) {
sendJSONresponse(res, 400, {
"message": "Device Mac-Address required"
});
return;
}
User.findOne({ username: req.params.username }, function(err, user) {
if (err) { return next(err); }
if (!user) { return sendJSONresponse(res, 400, {
"message": "user not found"
});
}
Device.findOne({macAddress : req.body.macAddress}, function(err, device){
if(err){return next(err);}
if(!device){
sendJSONresponse(res, 400, {
"message": "No device with that macaddress"
});
return;
}
User.find({ devices: { $elemMatch: { $eq: req.body.macAddress} } }, function(err, users){
if(err){return next(err);}
if(users){
sendJSONresponse(res, 400, {
"message": "Device already assigned to a user"
});
return;
}else{
user.devices.push(device._id);
user.save(function(err) {
if(err){return next(err);}
sendJSONresponse(res, 200, user);
});
}
});
});
});
});
after doing all this when i try using the api with postman is tells me The server couldn't send a response: please help me fix my code
You are pushing device Id to devices array
user.devices.push(device._id)
but you are trying to elemMatch macAddress
User.find({ devices: { $elemMatch: { $eq: req.body.macAddress} } }..
When it should be
User.find({ devices: { $elemMatch: { $eq: device._id} } }..
Your have to change elemMatch param to device._id to make it correct.
router.post('/user/device/:username', function(req, res, next) {
if(!req.body.macAddress) {
sendJSONresponse(res, 400, {
"message": "Device Mac-Address required"
});
return;
}
User.findOne({ username: req.params.username }, function(err, user) {
if (err) { return next(err); }
if (!user) { return sendJSONresponse(res, 400, {
"message": "user not found"
});
}
Device.findOne({macAddress : req.body.macAddress}, function(err, device){
if(err){return next(err);}
if(!device){
sendJSONresponse(res, 400, {
"message": "No device with that macaddress"
});
return;
}
User.find({ devices: { $elemMatch: { $eq: device._id} } }, function(err, users){
if(err){return next(err);}
if(users){
sendJSONresponse(res, 400, {
"message": "Device already assigned to a user"
});
return;
}else{
user.devices.push(device._id);
user.save(function(err) {
if(err){return next(err);}
sendJSONresponse(res, 200, user);
});
}
});
});
});
});
Use debugger to go through code step by step, and see what's going on. If you don't know how to debug, take a look at https://code.visualstudio.com/docs/editor/debugging. It is a free tool.

Mongoose objectId is not saving in another collection

I am new to mongoose and nodejs. Please help me to understand what is wrong in my code while saving collection. My user.js looks like below
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var UserSchema = new Schema ({
name: { type: String, required: true },
username:{ type:String, required: true, index:{ unique: true}},
password:{ type: String, required: true, select: false},
email:{ type: String, required: true, select: true},
mobile:{ type: String, required: true, select: true},
nativecid:{ type: Schema.Types.ObjectId, ref:'City'},
regdate:{ type: Date, default: Date.now },
did:{ type: String, required: false }
});
UserSchema.pre('save', function(next){
var user = this;
if(!user.isModified('password')) return next();
bcrypt.hash(user.password, null, null, function(err, hash){
if(err) return next(err);
user.password = hash;
next();
});
});
UserSchema.methods.comparePassword = function(password){
var user = this;
return bcrypt.compareSync(password, user.password);
};
module.exports = mongoose.model('User', UserSchema);
And my City model ie city.js looks like below
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CitySchema = new Schema({
name: { type: String, required: true },
status: { type: Boolean, default: true },
date: { type: Date, default: Date.now }
});
module.exports = mongoose.model( 'City', CitySchema );
City is already stored in database as below
{ "_id" : ObjectId("56a4a0adb0f445561cfd4e37"), "name" : "New York", "date" : ISODate("2016-01-24T10:00:13.220Z"), "status" : 1, "__v" : 0 }
I want this ObjectId of New York should be saved in user collection while user signups. I am trying like below but not succeed.
var User = require('../models/user');
var City = require('../models/city');
api.post('/signup', function(req, res){
var user = new User({
name: req.body.name,
username: req.body.username,
password: req.body.password,
email: req.body.email,
mobile: req.body.mobile
});
City
.findOne({ name: "New York" })
.populate('_id')
.exec(function (err, city1) {
if(err){
res.send(err);
return;
}
console.log('The creator is %s', city1.name);
return user.nativecid = city1._id;
})
user.save(function(err){
if(err){
res.send(err);
return;
}
res.json({
success: true,
message: 'User created successfully!'
});
});
});
I am not understanding what is wrong. Please advice me.
Just save user in city.findOne (nested) and may be no need to populate you should use projection.
City.findOne({ name: "New York" }, {name:1}) // ID return defaulat
.exec(function (err, city1) {
if(err){
res.send(err);
return;
}
console.log('The creator is %s', city1.name);
user.nativecid = city1._id;
user.save(function(err1){
if(err1){
res.send(err1);
return;
}
res.json({
success: true,
message: 'User created successfully!'
});
});
})

Resources