Mongoose: .save is not a function - javascript

I'm very new and I've looked through the archives but just what's going on in this code eludes me. I used express-generator to create a calendar app and now I want to hook it up to MongoDB. The actual connection to Mongo is working, but I can't get it to save a document.
The relevant portion of my global.js (where I'm running my front-end Javascript) looks like this:
$(document).ready(function() {
var ev = new Event({ date: "a6_13_2016", time: 900, description:"Fencing"});
ev.save(function(err) {
if (err) console.log(err);
else console.log("Success!")
})
This is where I'm getting the "TypeError: ev.save is not a function" message. My models/Events.js looks like this:
var mongoose = require('mongoose');
var eventSchema = new mongoose.Schema({
date: String,
time: Number,
description: String
});
module.exports = mongoose.model('Event', eventSchema);
My routes/events.js looks like this:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Event = require('../models/Events.js');
/* GET /event listing. */
router.get('/', function(req, res, next) {
Event.find(function (err, dates) {
if (err) return next(err);
res.json(dates);
});
});
/*POST event*/
router.post('/', function(req, res, next) {
Event.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
/* GET /event/id */
router.get('/:id', function(req, res, next) {
Event.findById(req.params.id, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
I want to save something to test it, but it's giving me ".save is not a function. Other than
var events = require('./routes/events');
app.use('/events', events);
and the code establishing the Mongoose connection my app.js file is boilerplate. What do you think is the problem?

I see
$(document).ready(function() {
Are you trying to use Mongoose in browser?
It's supposed to be used on the server-side.
In browser you need to send AJAX request to the server:
$('#save').click(function() {
$.post('/event', function(response) { console.log(reposne) })
});
On the server you should add a route that will handle your AJAX request, and inside this route you can save your model:
router.post('/event', function(req, res) {
var ev = new Event({ date: "a6_13_2016", time: 900, description:"Fencing"});
ev.save(function(err) {
if (err) console.log(err);
else console.log("Success!")
})
});
Please note that you don't need the 3rd param next in your rotues. It is used only in middlewares

Are you sure that line
var Event = require('../models/Events.js');
has the correct path?
You are creating an ev object from Event function and it seems that ev is undefined, judging from the error description.
If your Event file is not properly loaded you will not have access to .save function.

Related

updated a document with express

I'm trying to use the mongoDB and update the status of a current document. My backend is receiving the routes my mongoDB update isn't going through.
router.post('/orders_drivers', function (req, res, next) {
console.log(req.body);
Order.update({_id:objectId(req.body.id)}, {$set: {driver:req.body.driver, driverReq:false}}).then (function (order) {
console.log('UPDATE new driver');
}).catch (next)
});
when I log the req.body, the ID I receive and the new $set parameters are correct, but the command never goes through. Any suggestions? I don't receive any errors either which I think is strange.
Mongo version is v4.0.2
I have many other routes that all work correctly.
There is no version issue. you are calling then function on non promiseable value.
You need to call a callback function inside of update.
const mongoose = require('mongoose');
router.post('/orders_drivers', function (req, res, next) {
console.log(req.body);
Order.update({
_id: mongoose.Types.ObjectId(req.body.id)
},
{
$set: {
driver:req.body.driver, driverReq:false
}
},
{ new: true }, // If you want to return updated order
function (err, updatedOrder) {
if (err) throw err;
console.log('UPDATE new driver', updatedOrder);
})
});
You don't need to convert req.body.id into mongoose ObjectId if it already is.

returning data to index.js node express

Why is users undefined?
db.js:
var MongoClient = require('mongodb').MongoClient
var users;
MongoClient.connect('mongodb://127.0.0.1:27017/ExpressApp2', function(err, db) {
users = db.collection('usercollection');
users.find().each(function(err, doc) {
console.log(doc);
});
});
index.js
var express = require('express');
var router = express.Router();
/* GET Userlist page. */
router.get('/userlist', function(req, res) {
var users = require('../db').getUsers();
if (users==undefined)
res.send('undefined');
else
res.send('found something');
});
module.exports = router;
The collection is correctly retrieved from Mongo and logged to screen, but users in index.js gives undefined.
MongoClient.connect('mongodb://127.0.0.1:27017/ExpressApp2', function(err, db) {
users = db.collection('usercollection');
users.find().each(function(err, doc) {
console.log(doc);
});
});
should be
module.exports.getUsers = function() {
MongoClient.connect('mongodb://127.0.0.1:27017/ExpressApp2', function(err, db) {
return db.collection('usercollection');
});
}
I'm presuming that
users.find().each(function(err, doc) {
console.log(doc);
});
is part of your debugging and what you actually want to return is the user collection. The important bit is adding the block to module.exports as getUsers().
I got it to work with this async call in the end.
index.js
router.get('/userlist', function(req, res) {
var d = require('../db');
d.getUsers('input', function(users) {
users.each(function(err, doc) {
res.send(doc);
return false;
});
});
});
In db.js you are not using module.exports to export your users.
Your code in index.js suggests db.js exports an object with a getUsers function but it does not.

MongoDB and Express: Type Error: Converting Circular structure to JSON

I am new to MEAN stack. I am trying to retreive a list of documents from MongoDB. I have used Visual Studio 2013 community edition to create a basic Nodejs Express application. Visual studio created app.js file on the root for configuration. I have put following code in app.js which is relevant to mongodb:
var mongo = require('myDB');
var db = new mongo.Db("myDB", new mongo.Server("localhost", "27017"),
{ safe: true }, { auto_reconnect: true });
// Make our db accessible to our router
app.use(function (req, res, next) {
req.db = db;
next();
});
In the routes folder that visual studio created, I have created a js file which will perform CRUD operations. I have following code in this file:
var express = require('express');
var router = express.Router();
router.get('/myRecords', function (req, res) {
var db = req.db;
db.open(function (err, db) {
if (err)
console.log(err);
else {
var collection = db.collection('myCollection');
var dataToSend = collection.find();
res.send(dataToSend);
}
})
});
module.exports = router;
I am Type Error: Converting Circular structure to JSON.
I am trying to not using any schema.
Please advice.
For those of you, who encounter the similar problem, find() doesn't return the document, we need to use toArray to retrieve documents. Following code did the trick:
router.get('/myRecords', function (req, res) {
var db = req.db;
db.open(function (err, db) { // <------everything wrapped inside this function
db.collection('myCollection', function (err, collection) {
collection.find().toArray(function (err, items) {
res.send(items);
db.close();
});
});
});
});

Parsing nested JSON using body-parser and express

I have an iOS app which is sending a JSON packet to a webserver. The webserver code looks like this:
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var app = express();
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
console.log("MongoDB connection is open.");
});
// Mongoose Schema definition
var Schema = mongoose.Schema;
var LocationSchema = new Schema({
X: Number,
Y: Number,
Orientation: Number,
UserID: String,
Time: String
});
// Mongoose Model definition
var LocationsCollection = mongoose.model('locations', LocationSchema);
// create application/json parser
var jsonParser = bodyParser.json();
// URL management
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
app.post('/update', jsonParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
else {
console.log(req.body);
}
});
// Start the server
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log('App listening at %s:%s',host, port)
});
The key part is the app.post method which processes the incoming http request being sent from my iOS app. At the moment, the method which prints the req.body to the console looks like this:
{
datapoint_1:
{ timestamp: '2015-02-06T13:02:40:361Z',
x: 0.6164286615466197,
y: -0.6234909703424794,
id: 'B296DF8B-6489-420A-97B4-6F0F48052758',
orientation: 271.3345946652066 },
datapoint_2:
{ timestamp: '2015-02-06T13:02:40:961Z',
x: 0.6164286615466197,
y: -0.6234909703424794,
id: 'B296DF8B-6489-420A-97B4-6F0F48052758',
orientation: 273.6719055175781 }
}
So, you can see the request is a nested JSON object. Ideally, I'd like to loop through the request objects (ie. the datapoints) and insert those into the mongoDB database (via mongoose). However, I can't seem to figure out how to do much of anything with the req.body. I can't seem to create a loop to iterate through the request or how to properly parse the nested JSON file so it matches the mongoose schema. Can anyone provide some guidance on how to insert these datapoints into the mongoose database?
Set body-parser's extended property to true to allow parsing nested objects.
var express = require('express');
var app = express()
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: true
}));
Answering my own question. But, after figuring out how to access the key/value pairs inside the nested JSON object... it became relatively easy to figure out the rest. The updated app.post function now looks like this:
app.post('/update', jsonParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
else {
for(var datapoint in req.body){
//create new instance of LocationCollection document
var point = new LocationsCollection({
X:Number(req.body[datapoint]["x"]),
Y:Number(req.body[datapoint]["y"]),
Orientation:Number(req.body[datapoint]["orientation"]),
Time:req.body[datapoint]["timestamp"],
UserID:req.body[datapoint]["id"]
});
//insert the newly constructed document into the database
point.save(function(err, point){
if(err) return console.error(err);
else console.dir(point);
});
}
}
});
I can test if this worked by putting the following method inside the callback function once the mongodb connection is first established:
//Find all location points and print to the console.
console.log("Searching for all documents in Location Points Collection");
LocationsCollection.find(function(err,data){
if(err) console.error(err);
else console.dir(data);
});
This will print any documents that have been previously added to the database. Hopefully this helps.
Try somthing like this.
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json({limit:1024*1024, verify: function(req, res, buf){
try {
JSON.parse(buf);
} catch(e) {
res.send({
error: 'BROKEN_JSON'
});
}
}}));
It should be a simple for (var key in obj) loop:
app.post('/update', jsonParser, function (req, res) {
var locationObject = req.body(),
insertObjects = [],
key;
for (key in locationObject) { // loop through each object and insert them into our array of object to insert.
insertObjects.push(locationObject[key]);
}
if (!insertObjects.length) { // if we don't have any object to insert we still return a 200, we just don't insert anything.
return res.status(200).send({
success: true,
message: 'Nothing inserted, 0 locations in POST body',
count: 0;
});
}
LocationsCollection.create(insertObjects, function (err, res) {
if (err) {
return res.status(400).send({
success: false,
message: err.message
});
}
// we have successfully inserted our objects. let's tell the client.
res.status(200).send({
success: true,
message: 'successfully inserted locations',
count: insertObjects.length;
});
});
});
Mongo allows for inserting multiple documents with a single callback, which makes this a lot easier.
This also checks the schema to ensure only proper documents are created.

In a Node web app, do you open one MongoDB connection for each HTTP request?

I'm adding MongoDB to my Express.js Node web app. This is what I got so far:
// in app.js
var mongodb = require('mongodb');
var mongourl = /* … */;
// These are just examples:
app.get('/write', function (req, res) {
mongodb.connect(mongourl, function (err, db) {
db.collection('Users', function (err, coll) {
coll.insert(/* stuff */, function (err) {
res.send(200, 'Done.');
});
});
});
});
app.get('/read', function (req, res) {
mongodb.connect(mongourl, function (err, db) {
db.collection('Users', function (err, coll) {
coll.find({}, function (err, cursor) {
cursor.toArray(function (err, items) {
res.send(200, items);
});
});
});
});
});
Assuming that I want to stick with the default mongodb driver (for now):
Is this pattern right? Do I have to open a new connection to the database in each of my different routes that perform database operations?
If the pattern is right, then how do I deal with the obvious code repetition going on here? Obviously, as it stands now, the code is not acceptable.
Use the new standard, MongoClient. It manages the pool for you, defaults to 5.
//require as a module to be used anywhere.
module.exports = {}
var MongoClient = require('mongodb').MongoClient;
var mongoURI = /* … */;
MongoClient.connect(mongoURI, function(err, db) {
if(err) throw err;
module.exports.users = db.collection('users');
console.log('Connected to Mongo!')
})
then
var db = require('./db.js')
//once connected
//db.users.find()... etc
check out:
http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html
pooling details:
http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html#connection-pool-configuration
Do not close and reopen connection, you're just loosing resources :s

Categories