save method in Mongoose failed - javascript

I tried to use save() in Mongoose but saw empty collection been inserted.
my photo schema is like this :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var photosSchema = mongoose.Schema({
photos: {
type: String
},
caption: {
type: String
}
});
var Photos = module.exports = mongoose.model('photos', photosSchema);
module.exports.getAllPhotos = function(callback){
Photos.findAll(callback);
}
and in my route I do
var Photo = require('../models/photos');
router.post('/upload_photo', upload.any(), function(req, res, next) {
var photo = new Photo();
var data = {
photos:'abc.jpg',
caption:'something..'
}
photo.save(data);
res.end();
});
Am I using save wrong here? I know I can define a method like savePhoto and export it, but how to use save() directly instead?

Try it like so, i.e. pass the data directly to the constructor and end the response stream when the async. save finished (and maybe add error handling as well).
var photo = new Photo({
photos:'abc.jpg',
caption:'something..'
});
photo.save(function(err) {
res.end();
});
There is also a shorthand create method on the model as described in the Mongoose docs

Try like this, and you will be able to see the issue if there's any:
var data = {
photos:'abc.jpg',
caption:'something..'
};
var photo = new Photo(data);
photo.save(function (err) {
if (err) console.log(err);
res.end();
});

Related

Node.js mongoose .findOne is not a function

In my app, I do return promise with my mongoose model:
var roomModel = require('../../../models/room').roomModel;
roomModel.findOne({ name: req.body.roomName })
.then(
(room) => {
return new Promise(function(resolve, reject) {
//if no room present, create one, if present, check password
if (room) {
if (room.password === req.body.roomPassword) {
return resolve(room);
} else {
return reject({
code: 401,
message: 'Room password not correct'
});
}
} else {
// create new room with given data
var newRoom = roomModel({});
newRoom.name = req.body.roomName;
newRoom.password = req.body.roomPassword;
//newRoom.users = [];
newRoom.users[0] = {
name: req.body.userName
};
newRoom.save()
.then((data) => {
console.log(data);
if (!data) {
return reject({
code: 500,
message: 'Error when saving room'
});
} else {
return resolve(newRoom);
}
});
}
});
}
)
.then((room) => {
room.findOne({ 'users.name': req.body.userName })
.then((user) => {
console.log(user);
});
})
room.js model:
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = require('./user').userSchema;
var room = new Schema({
name: String,
password: String,
users: [userSchema]
});
module.exports.roomSchema = room;
module.exports.roomModel = mongoose.model('room', room);
users.js model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var user = new Schema({
name: String
});
module.exports.userSchema = user;
module.exports.userModel = mongoose.model('user', user);
but when I try to call .findOne() function on this returned model, I get following error:
TypeError: room.findOne is not a function
is model passed in the promise not a model in next .then() statement?
Found problem by myself: I was passing not the model, on which I can use find operations, but document, on which I can perform save options (not find, since it's not a model).
Well, as the docs say "queries are not promises".
There's even a findOne() example in there...
Change your code to
roomModel.findOne({ name: req.body.roomName }).exec().then(/* your stuff */)
and you may have more luck.
You missed out exec() method in your query, try to use and get resolved.
roomModel.find({ name: req.body.roomName }).exec().then(/* your stuff */)
I should think what you're doing is dangerous. Calling a queries then() multiple times might
lead to multiple query calls.
https://mongoosejs.com/docs/queries.html#queries-are-not-promises
Also, there is no need to do exec().then(). Just calling then() executes the query; a better way to use exec() is to actually pass a callback to it.
in my case it happened that no matter how I exported it it wasn't working, and I found this solution:
var {roomModel} = require('../../../models/room')
Put the import within {}
and export it normally, i do like this:
var room = mongoose.model('room',roomSchema);
module.exports.room = room;

TypeError: populate(...).exec is not a function

I largely believe this error is due to the object I'm calling not containing the .populate function, although I have no idea how to change this to work.
To start with, here is the error in full.
TypeError: exam[0].modules[u].topics[i].populate(...).exec is not a function
at /home/ubuntu/workspace/tests/app.js:425:84
at Query.Model.$wrapCallback (/home/ubuntu/workspace/tests/node_modules/mongoose/lib/model.js:3336:16)
at /home/ubuntu/workspace/tests/node_modules/mongoose/node_modules/kareem/index.js:259:21
at /home/ubuntu/workspace/tests/node_modules/mongoose/node_modules/kareem/index.js:127:16
at nextTickCallbackWith0Args (node.js:420:9)
at process._tickCallback (node.js:349:13)
Process exited with code: 1
The specific line I'm referring to is exam[0].modules[u].topics[i].populate("questions").exec(function(err,quests) another line I believe is significantly important here is the line examBoard.find({name:req.body.examBoardName},function(err,exam) which returns exam which does not contain the .populate function.
I presume this is largely down to my lack of experience, and not a logical error, but I'm not sure.
Here is the section of code which contains the error.
app.post("/test",function(req,res)
{
console.log("\n\n\n\n")
var time = req.body.time;
var topicName = [req.body.topic1,req.body.topic2,req.body.topic3,req.body.topic4,req.body.topic5];
var topicsArray = [];
examBoard.find({name:req.body.examBoardName},function(err,exam)
{
if(err)
{
console.log(err);
}
else
{
for(var u=0;u<exam[0].modules.length;u++)
{
console.log("exam[0].modules[u]:\n"+exam[0].modules[u]);
console.log("req.body.moduleName:\n"+req.body.moduleName);
if(exam[0].modules[u].name==req.body.moduleName)
{
console.log("topicName[]:\n"+topicName[0]+"\n"+topicName[1]+"\n"+topicName[2]+"\n"+topicName[3]+"\n"+topicName[4]);
for(var i=0;i<exam[0].modules[u].topics.length;i++)
{
console.log("exam[0].modules[u].topics[i].name:\n"+exam[0].modules[u].topics[i].name);
for(var t=0;t<topicName.length;t++)
{
if(exam[0].modules[u].topics[i].name==topicName[t])
{
// exam[0].modules[u].topics[i].find({name:topicName[t]}).populate("questions").exec(function(err,quests)
exam[0].modules[u].topics[i].populate("questions").exec(function(err,quests)
{
if(err)
{
console.log(err);
}
else
{
console.log("exam[0].modules[u].topics[i].questions:\n"+exam[0].modules[u].topics[i].questions);
topicsArray.push({
name:topicName[i],
questions:quests
});
}
});
}
}
}
break;
}
}
}
});
});
Here is the examBoard schema.
var mongoose = require("mongoose");
var topicSchema = new mongoose.Schema({
name: String,
questions:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"question"
}
],
});
var moduleSchema = new mongoose.Schema({
name: String,
topics: [topicSchema]
});
var examBoardSchema = new mongoose.Schema({
name: String,
modules: [moduleSchema]
});
module.exports = mongoose.model("examBoard", examBoardSchema);
And here just in case there may be something wrong here, is the importing of the schema.
var express = require("express"),
mongoose = require("mongoose"),
passport = require("passport"),
bodyParser = require("body-parser"),
LocalStrategy = require("passport-local"),
passportLocalMongoose = require("passport-local-mongoose"),
seedDB = require("./seeds"),
question = require("./models/question"),
examBoard = require("./models/examBoard"),
user = require("./models/user");
You are invoking populate method from exam[0].modules[u].topics[i] but actually the model object that hold this method is exam[0] so you can populate questions in your exam in a deep object-hierarchy like this:
exam[0].populate("modules.topics.questions")
But, wait a sec, now the model will populate the questions in all topics in all modules within this exam.
In your case, you filter by moduleName first, so you can configure populate options, so to be like this:
var options = {
path: 'modules.topics.questions',
match: { 'modules.name': req.body.moduleName }
};
exam[0].populate(options)
Lear more about populate parameters from docs.

How to get Mongoose to list all documents in the collection? To tell if the collection is empty?

I'm using a MEAN stack and writing these methods in Mongoose. I'm wondering what's wrong with what I put in the Mongoose model file. I would like to use Mongoose to simply print out a list all the documents in the myModel collection.
myModel.methods.myMethod = function(cb){
this.model("Bids").find({}, 'myField', function(err, results){
if (err){console.log(err);return err;}
console.log("okay");
console.log(results);
})
this.save(cb);
}
Also, what is the code that I can write in Mongoose to tell if the myModel collection is empty or not?
It's better to teach a man how to fish than to give him a fish ...
So it would be extremely helpful if you can suggest what debugging tools I can install, such as an Express middleware, that can help me debug myself. Please post your debugging suggestions here.
I'm assuming every other setup required for mongoose is correct.
At the line below, I think 'myField' is not needed.
this.model("Bids").find({}, 'myField', function(err, results)
Here is something more from scratch, maybe it would help you to trace-back you steps:
var mongoose = require('mongoose');
//connection to Mongodb instance running on=======
//local machine or anywhere=========================
var uri = 'mongodb://localhost:27017/test';
var connection = mongoose.createConnection(uri);
//Define Schema==================================
var Schema = mongoose.Schema;
var BlogPostSchema = new Schema({
author: { type: Schema.Types.ObjectId },
title: String,
body: String
});
//Create model===================================================
var BlogPostModel = connection.model('BlogPost', BlogPostSchema);
//function to insert doc into model NOTE "pass in your =======
//callback or do away with it if you don't need one"=========
var insertBlogPost = function (doc, callback) {
//here is where or doc is converted to mongoose object
var newblogPost = new BlogPostModel(doc);
//save to db
newblogPost.save(function (err) {
assert.equal(null, err);
//invoke your call back if any
callback();
console.log("saved successfully");
});
};
//function to get all BlogPosts====================================
var getAllBlogPosts = function (callback) {
//mongoose get all docs. I think here answers your question directly
BlogPostModel.find(function (err, results) {
assert.equal(null, err);
//invoke callback with your mongoose returned result
callback(results);
});
};
//you can add as many functions as you need.
//Put all of your methods in a single object interface
//and expose this object using module.
var BlogPostManager = {
insertBlogPost: insertBlogPost,
getAllBlogPosts : getAllBlogPosts
}
module.exports = BlogPostManager;

Fetching collections via Mongoose fails(Object {} has no method 'find')

I want to fetch some collections via Mongoose find method. My model is like this:
var mongoose = require('mongoose');
var schema = new mongoose.Schema({
timeline_content: String,
timeline_e_id: String
});
var timeline = mongoose.model('timeline', schema);
module.exports = timeline;
and with this code i want to fetch some collections:
var Timeline = require('./models/timeline');
var timeline = new Timeline();
timeline.find({timeline_e_id:'an id'}).sort("_id").limit(5).exec(
function(err, projects) {
if (err) {
throw err;
}
//do something
}
);
But i get this error:
TypeError: Object {} has no method 'find'
Why? i have to define find method inside my model? Actually i can't find any resource to do queries. This is simplest one but it fails.
.find is a method on your TimeLine model, not on an instance of TimeLine.
Drop the new and the () from your variable assignment.
EDIT
As suggested by Blakes Seven, your code should look like this:
var Timeline = require('./models/timeline');
TimeLine.find({timeline_e_id:'an id'}).sort("_id").limit(5).exec(
function(err, projects) {
if (err) {
throw err;
}
//do something
});

What is the correct way of passing a Mongoose object into the MongoDB underlying connection insert() method

I need to insert many thousands of documents into MongoDB. I want to use Mongoose for its casting properties, etc. However I cannot figure out how to pass the generated instances to the MongoDB connection. I have tried this:
var fs = require('fs');
var mongoose = require('mongoose');
var config = JSON.parse(fs.readFileSync("./config.json"));
mongoose.connect(config.mongoDBUrl);
db = mongoose.connection;
db.once('open', function () {
var TestSchema = new mongoose.Schema({
testStr : String
});
var Model = mongoose.model('test_schema_2', TestSchema);
var inst = new Model();
inst.testStr = "EWAFWEFAW";
// This works.
db.collection('test_schema_2').insert({ testStr : 'My Test Str'}, {}, function (err) {
if (err) {
console.log(err);
} else {
console.log('Written.');
db.close();
}
});
// This doesn't.
db.collection('test_schema_2').insert(inst, {}, function (err) {
if (err) {
console.log(err);
} else {
console.log('Written.');
db.close();
}
});
});
In the second case, I get: "[RangeError: Maximum call stack size exceeded]"
What is Mongoose breaking behind the scenes that stops this from working, and how can I make it work?
To save an instance of a model you just have to do
inst.save(function(err) {
//Do something here
});

Categories

Resources