I am developing a web app using nodejs, angular, mongo. Having a weird problem. Model is not binding properly from json object.
this is my Schema.
var mongoose = require('mongoose');
var productSchema = new mongoose.Schema({
name : {type: String},
imageURL : {type: String, default: '/'},
created : {type: Date, default: Date.now}
});
module.exports = mongoose.model('product', productSchema);
And I am passing the product using POST to my index.js.
router.post('/pictures/upload', function (req, res, next) {
uploading(req, res, function(err){
if (err) {
console.log("Error Occured!");
return;
}
var product = new productModel(req.body.pName);
product.imageURL = req.file.path;
product.update(product);
res.status(204).end();
});
var product only consists of _id, created, imageURL. not the name property.
But console.log(req.body.pName) prints out {"_id":"56d80ea79d89091d21ce862d","name":"sunny 2","__v":0,"created":"2016-03-03T10:15:03.020Z","imageURL":"/"}
Its not getting the name property. Why is that???
Please advise.
Found the Solution. It wasn't binding properly because content-type was in multipart/form-data. I had to parse the jSON object, like this:
var product = new productModel(JSON.parse(req.body.pName));
pName had the values in a string.
Hope this helps someone.
Try this way, You just creating instance of Product object and then updating.
var Product = mongoose.model('products');
uploading: function(req, res) {
// console.log(req.body); find your object
// in your case it looks req.body.pname
var product = new Product(req.body.pname);
product.imageURL = req.file.path;
product.save(function (err, product) {
if (err){
console.log(err);
}else{
res.status(204).end();
// it returns json object back - callbcak
// res.json(product);
}
})
},
Related
I have 2 collections that I declared in my comments.model file:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
require('./util');
var currentDate = new Date().getDate();
var currentMonth = new Date().getMonth()+1;
var currentYear = new Date().getFullYear();
var battleFieldOneCommentsSchema = new Schema( {
user_name: {type: String},
comment: {type: String},
date_created: {type: String, default: String(currentDate+"/"+currentMonth+"/"+currentYear)},
likes: {type: Number, default: 0},
dislikes: {type: Number, default: 0}
});
module.exports = mongoose.model('battlefieldOne_Comments', battleFieldOneCommentsSchema);
module.exports = mongoose.model('another_game_Comments', battleFieldOneCommentsSchema);
I have an index.js file that has API's to insert comments into the database:
var battlefieldOne_Comments = require('../models/comments');
var anotherGame_Comments = require('../models/comments');
router.post('/add_battlefieldOne_Comment', function(req, res, next) {
comment = new battlefieldOne_Comments(req.body);
comment.save(function (err, savedComment) {
if (err)
throw err;
res.json({
"id": savedComment._id
});
});
});
router.post('/add_anotherGame_Comments', function(req, res, next) {
comment = new anotherGame_Comments(req.body);
comment.save(function (err, savedComment) {
if (err)
throw err;
res.json({
"id": savedComment._id
});
});
});
module.exports = router;
When I use that API, it inserts the same comment into both collections on the database. I know this is because both comments variables in the index.js file require the same file. Is there a way to fix this, because I don't want to make a new model file for each schema. I am new to nodejs and mongoose, so this might be a silly question, but is there a way to define a single schema and use that schema for a lot of collections, while still being able to update those collections separately and independently?
The way you are exporting and requiring your models in index.js won't have the effect you want.
When you use module.exports like that you're not giving the values you're exporting a name, so when require is called on that file, you'll end up requiring the same value for both of your variables.
What you wanna do here is set your models to different variables and then export those:
var battlefieldOneComments = mongoose.model('battlefieldOne_Comments', battleFieldOneCommentsSchema);
var anotherGameComments = mongoose.model('another_game_Comments', battleFieldOneCommentsSchema);
module.exports = {
battlefieldOneComments : battlefieldOneComments,
anotherGameComments : anotherGameComments
}
After that you require them by accessing those in index.js:
var battlefieldOne_Comments = require('../models/comments').battlefieldOneComments;
var anotherGame_Comments = require('../models/comments').anotherGameComments;
That way you're not requiring the same model for both variables and it should save your comments on different collections.
I'm learning Angular by following this tutorial. No what I don't get is why is there two ways of saving/editing an object? They don't really explain it.
first way (in the index.js router):
router.post('/posts', function(req, res, next) {
var post = new Post(req.body);
post.save(function(err, post) {
if (err) { return next(err); }
res.json(post);
});
});
second way (in the mongoose model):
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
PostSchema.methods.upvote = function(cb) {
this.upvotes += 1;
this.save(cb);
};
mongoose.model('Post', PostSchema);
The two ways are actually the same.
In the first example a new instance of Post is created. The save is called on this instance because it exists on PostSchema (inherited from Mongoose Schema).
In the second example we define a new method on PostSchema so when invoked, this refers to the instance of the Post.
The cb parameter is a callback which is normally a function.
Look at this example.
router.post('/posts', function(req, res, next) {
var post = new Post(req.body);
post.save(function(err, post) {
if (err) { return next(err); }
var callback = function(err, post) {
console.log("Upvoted");
res.json(post);
}
post.upvote(callback);
});
});
Here a new post is created with one upvote by default.
A new instance of Post is created and saved in the db. After save, upvote method is called. After the upvote was saved in the db, the new post is returned in the response.
Hope this helps.
The first part is a normal Mongoose save in which you create a new object from the schema. The second is having a method defined in the schema to handle the save.
PostSchema.methods.upvote = function(cb) {
this.upvotes += 1;
this.save(cb);
};
For example, assuming I already have a saved post and I want to upvote it. I can have a route like this:
router.put('/post/:id/upvote', function(req, res, next) {
Post.findOne({_id: req.params.id}, function (error, post) {
post.upvote(function(error, post) {
res.json(post);
});
});
});
In simple terms, the code above makes use of the inbuilt "upvote" method that is already defined in the Schema, so all objects created from the Schema will have an "upvote" method that will increase the number of upvotes. It is the same thing as doing this:
router.put('/post/:id/upvote', function(req, res, next) {
Post.findOne({_id: req.params.id}, function (error, post) {
post.upvotes += 1;
post.save(function(error, post) {
res.json(post);
});
});
});
Just that it is cleaner and saves you a few keystrokes.
'Im trying to have an array of patients Objectids and an array of data(information about doctor) objectids inside the doctors collection. This is the beginning of the code then I got lost. I think I want to use something like this Doctor.find().populate('patients data'). Then if someone could show me how to access the information that would be great.
var express = require("express");
var app = express();
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/population")
var doctorSchema = new mongoose.Schema({
name : String,
patients : [{type : mongoose.Schema.Types.ObjectId, ref : "Patient"}],
data : [{type : mongoose.Schema.Types.ObjectId, ref : "Data"}]
})
var patientSchema = new mongoose.Schema({
name : String
})
var dataSchema = new mongoose.Schema({
income : String
})
var Doctor = mongoose.model("Doctor",doctorSchema );
var Patient = mongoose.model("Patient", patientSchema);
var Data = mongoose.model("Data", dataSchema);
var doc1 = new Doctor({"name" : "doc1"})
doc1.save(doc1, function(err, doc){
if(err){
console.log(err)
}else{
console.log("saved")
}
})
app.listen(3000, function(){
console.log("listening on 3000");
})
To access the information, the app should be able to receive requests; a 'get' method needs to be defined on the app object:
app.get('/:id', function(req, res) {
var doctorID = req.params.id;
Doctor
.findOne({_id: doctorID})
.populate('patients data')
.exec(function(err, doctor) {
if (err) throw err;
res.send(doctor);
});
});
I am currently attempting to create a .post function for a schema with document reference. However, I am not sure how I can retrieve the ObjectID of the document reference from another collection.
Board.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BoardSchema = new Schema({
boardname: String,
userid: {type: Schema.ObjectId, ref: 'UserSchema'}
});
module.exports = mongoose.model('Board', BoardSchema);
User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String
});
module.exports = mongoose.model('User', UserSchema);
routes.js
router.route('/boards')
.get(function(req, res) {
Board.find(function(err, boards) {
if(err)
res.send(err);
res.json(boards);
});
})
.post(function(req, res) {
var board = new Board();
board.boardname = req.body.boardname;
User.find({username: req.body.username}, function(err, user) {
if(err)
res.send(err);
board.userid = user._id;
});
board.save(function(err) {
if(err)
res.send(err);
res.json({message: 'New Board created'});
});
});
To create the board, I include a boardname and a username in my request. Using the username, I do a User.find to find the specific user and assign it to board.userid. However, this does not seem to be working as board.userid does not appear.
Any help would be greatly appreciated!
Thank you!
EDIT
A better explanation of what is required is that I have an existing User collection. When I want to add a new document to Board, I would provide a username, from which I would search the User collection, obtain the ObjectId of the specific user and add it as userid to the Board document.
I believe you are looking for population
There are no joins in MongoDB but sometimes we still want references
to documents in other collections. This is where population comes in.
Try something like this:
//small change to Board Schema
var BoardSchema = new Schema({
boardname: String,
user: {type: Schema.ObjectId, ref: 'User'}
});
//using populate
Board.findOne({ boardName: "someBoardName" })
.populate('user') // <--
.exec(function (err, board) {
if (err) ..
console.log('The user is %s', board.user._id);
// prints "The user id is <some id>"
})
Sorry, I solved a different problem previously. You'll probably want to use the prevoius solution I provided at some point, so I'm leaving it.
Callbacks
The reason the userid is not on the board document is because User.find is asynchronous and is not assigned at the moment board.save(...) is called.
This should do the trick:
(Also, I added a couple of returns to prevent execution after res.send(...))
.post(function(req, res) {
var board = new Board();
board.boardname = req.body.boardname;
User.find({username: req.body.username}, function(err, user) {
if(err)
return res.send(err); //<-- note the return here!
board.userid = user._id;
board.save(function(err) {
if(err)
return res.send(err); //<-- note the return here!
res.json({message: 'New Board created'});
});
});
});
I am trying to create a User list when user submit their details. In app.js I have the function for that.
like this:
app.post('/addList', userList.submit);
I am calling my function which is nested in userList.submit:
var sendList = require('../model/model');
exports.list = function(req, res){
res.send("respond with a resource this is from list file");
};
exports.addList = function(req, res, next){
res.render('index', {title:'title from list.js'});
};
exports.submit = function(req,res,next){
var name = req.body.name,
dept = req.body.dept;
sendList.create({
name:name,
dept:dept
}, function(error){
console.log('Erros is ', error);
if (error) return next(error);
res.redirect('/');
});
};
In the model folder, model.js has the function as follows:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/user_list');
var schema = new Schema({
name:String,
dept:String
});
module.exports = mongoose.model('User', schema);
But I am getting error saying:
var schema = new Schema({
^
ReferenceError: Schema is not defined
What is this mean? where I made the mistake? any one figure out and help me to solve this?
Schema is defined as a property of mongoose. It's not there in the global scope of nodejs.
var schema = new mongoose.Schema({
name:String,
dept:String
});
Schema is part of an application or is a property of mongoose. It has nothing to do with db, it's only mapping db into js objects.
you have to change the code : = new mogoose.schema ({ what ever you want ..