Cannot overwrite `Kitten` model once compiled - node.js

I've run into an issue with the Mongoose Getting Started guide.
I have MongoDB running and everything is working perfectly until I add the last line:
Kitten.find({ name: /^Fluff/ }, callback)
When I node server.js I get this error:
OverwriteModelError: Cannot overwrite Kitten model once compiled.
Here's the full error and my server.js.
Any idea what I'm doing wrong?
P.S. I'm running node 10.26, npm 1.4.13, express 4.4.3 & mongoose 3.8.12 on OS X 10.9.3.

You get the error because callback in Kitten.find({ name: /^Fluff/ }, callback) calls var Kitten = mongoose.model('Kitten', kittySchema); again. Change
Kitten.find({ name: /^Fluff/ }, callback)
to something like:
Kitten.find({ name: /^Fluff/ }, function(err, kittens) {
});
It doesn't make sense to call the callback function again.

I thought this could be useful to someone else who tries it...
I started looking into mongoose and tried Getting Started guide. I don't see the above error happening where it was reported. However, I did see it intermittently. If it happens, follow #3 below. Here are my observations:
Issue#1. If I copy paste the whole code I see an issue with "I don't have a name" as the single quote in don't is not escaped.
Solution#1. I tried to escape with \ and \\ but it didn't work. Google search didn't help. After some research I found that it is forgiving for single quotes outside the function. But, inside the function it won't work. So, I defined a variable outside the function. Probably better to define strings in a separate document for localization anyways. Above all, it works. :)
Issue#2. I see the issue at
fluffy.speak();
TypeError: fluffy.speak is not a function
Here since the first 'mongoose.model(...)' doesn't have this method, adding it later and re-running 'mongoose.model(...)' will not help.
Solution#2. Comment the first 'mongoose.model(...)'
Issue#3. When I copy paste the code from the web site, it is causing weird errors.
Solution#3. Just deleted all the tabs and empty spaces at the end of lines in a Notepad++. That took care of it.
Here is the code that worked for me (Needless to say, if it doesn't work, please copy paste first in notepad):
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection.error:'));
db.once('open', function(callback) {
//yay!
});
var kittySchema = mongoose.Schema({
name: String
});
//var Kitten = mongoose.model('Kitten', kittySchema);
//var silence = new Kitten({ name: 'Silence' });
//console.log(silence.name);
//console.log(silence);
var noname = "I don't have a name";
kittySchema.methods.speak = function () {
var greeting = this.name
? "Meow name is " + this.name
: noname;
console.log(greeting);
}
var Kitten = mongoose.model('Kitten', kittySchema);
var fluffy = new Kitten({ name : 'fluffy' });
fluffy.speak();

Related

Why is node stuck in a loop after loading a file requiring Mongoose?

I am very new to coding and I am taking Colt Steele's web development bootcamp course online. The course has been great so far, however I think some portions are outdated.
When I am in node and enter .load .index.js, the terminal gets stuck in some sort of loop and continuously prints "const mongoose = require('mongoose')." I pasted my code below if that helps. Please let me know if you think you know my error, thank you!
const mongoose = require('mongoose');
mongoose.set('strictQuery', false);
mongoose.connect('mongodb://127.0.0.1:27017/movieApp')
.then(() => {
console.log("connection open!");
})
.catch(err => {
console.log("oh no, error!");
console.log(err);
})
const movieSchema = new mongoose.Schema( {
title: String,
year: Number,
score: Number,
rating: String
})
const Movie = mongoose.model('Movie', movieSchema);
I tried resaving the file, and attempting different ways to connect to the database. However, each time I still got the same loop. I am hoping for node to load my code and enter the REPL.
I found the answer in the question forum in the course I am taking. The TA posted this:
UPDATE (SOLUTION):
This seems like a bug with the newest versions of node with how it works with mongoose.
Instead of using .load index.js inside of the node shell, use the command
node -i -e "$(< index.js)" in the system terminal (outside of the node shell, just be sure that you first change directories into the folder containing the index.js file) — this will load the file and start the node with this one command instead, and then it should work.

require() not working inside module.exports

I've been playing with nodejs for a few months now but from last night it stated acting funny.
It's such a stupid problem that is better explained with an example.
This is my code:
FILE-A:
var Q = require('q');
var user = require('../p/user');
module.exports = {
test: function() {
console.log("*****************************************");
console.log(user);
console.log(require('../p/user'));
console.log("*****************************************");
}
};
and FILE-B:
var fileA = require('../fileA');
var Q = require('q');
fileA.test();
Very simple! The problem is that "user" imported into FILE-A is empty! This is the output:
*****************************************
{}
{ get: [Function],
update: [Function],
getProfilePicture: [Function] }
*****************************************
As you can see if I call directly require() in the code, everything is fine!
I feel stupid cause obviously is my fault but I cannot find a solution. do you have any idea of what can be causing this problem?
Thanks a lot!
UPDATE: this is the ../p/user file
/************************************
*
***********************************/
var Q = require('q');
var cassandra = require('../../db/cassandra');
var dateManager = require('../../commons/DateManager');
var db = "test";
var table = "user";
module.exports = {
...
};
Solved....but you are not going to like it, I just reinstalled nodejs and everything is fine now! (same version - v4)
I'm very upset, this is not the way I like to deal with problems and it's seriously shaking my confidence in nodejs. On the other hand, it's such a basic/common scenario that I'm keen on saying it was my fault!
Sorry for the non-solution!

nodeschool:learnyoumongo "FIND" lesson fails before I write anything - config?

Currently the only thing I have in my file is the following:
var mongo = require('mongodb').MongoClient,
url = 'mongodb://localhost:27017/learnyoumongo';
console.log(mongo);
When I run the verify command, I get the following error:
/usr/local/lib/node_modules/learnyoumongo/exercises/find/exercise.js:37
db.collection('parrots').remove({}, function(err) {
^
TypeError: Cannot read property 'collection' of undefined
at Exercise.<anonymous> (/usr/local/lib/node_modules/learnyoumongo/exercises/find/exercise.js:37:5)
at next (/usr/local/lib/node_modules/learnyoumongo/node_modules/workshopper-exercise/exercise.js:260:17)
at Exercise.end (/usr/local/lib/node_modules/learnyoumongo/node_modules/workshopper-exercise/exercise.js:266:5)
at Workshopper.end (/usr/local/lib/node_modules/learnyoumongo/node_modules/workshopper/workshopper.js:191:12)
at Workshopper.done (/usr/local/lib/node_modules/learnyoumongo/node_modules/workshopper/workshopper.js:323:19)
at Exercise.<anonymous> (/usr/local/lib/node_modules/learnyoumongo/node_modules/workshopper-exercise/exercise.js:149:14)
at /usr/local/lib/node_modules/learnyoumongo/node_modules/workshopper-exercise/exercise.js:136:16
at Exercise.<anonymous> (/usr/local/lib/node_modules/learnyoumongo/node_modules/workshopper-exercise/filecheck.js:10:14)
at FSReqWrap.oncomplete (fs.js:95:15)
When I took a look at the exercises.js file, I see the error is pointing to the .addCleanup function and the db it is trying to close is undefined.
This seems like a connection/configuration error, but I passed the first two modules. Can anyone help?
Update
This is definitely a connection error. The previous scenario was created using the command in the workshop module mongod --port 27017 --dbpath=./data, however when I opened a new terminal tab and just ran mongo without any arguments, the verify command actually output the "Actual/Expected" evaluation and module results.
To the user who asked for the rest of the script, please understand if you are unfamiliar with nodeschool that this is an entire repository with module based automated/interactive tutorials, so this is not all of the code. In any case, here is what you requested:
var mongo = require('mongodb').MongoClient
, exercise = require('workshopper-exercise')()
, filecheck = require('workshopper-exercise/filecheck')
, execute = require('workshopper-exercise/execute')
, comparestdout = require('workshopper-exercise/comparestdout')
exercise = filecheck(exercise)
exercise = execute(exercise)
exercise = comparestdout(exercise)
var db, url = 'mongodb://localhost:27017/learnyoumongo'
exercise.addSetup(function(mode, cb) {
var self = this
this.submissionArgs = [3]
this.solutionArgs = [3]
mongo.connect(url, function(err, _db) {
if (err) return cb(err)
db = _db
col = db.collection('parrots')
col.insert([{
name: 'Fred'
, age: 1
}, {
name: 'Jane'
, age: 3
}, {
name: 'Jenny'
, age: 10
}], cb)
})
})
exercise.addCleanup(function(mode, pass, cb) {
db.collection('parrots').remove({}, function(err) {
if (err) return cb(err)
db.close()
cb()
})
})
module.exports = exercise
I think that should be:
var mongo = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/learnyoumongo', function(err, db) {
console.log(err);
});
There was definitely a connection problem. I'm not sure exactly where the bug was, but I reloaded learnyoumongo and reinstalled a couple of node packages. When I did that I had to go back and change permissions on the data directory again.
My recommendation if anyone else faces strange config errors, is to try to reinstall. Then when you connect, it doesn't hurt to re-verify the CONNECT module to make sure you have a good connection when you start your work space.

Why doesn't my Mongoose schema method "see" my required object?

I'm really confused about a variable scope issue with a file required via a path in a config file. Why does my Mongoose schema method "see" the required objects when called from within the model file but not when called from my app.js file? I'm convinced that I must be doing something obviously wrong but I can't see it.
The Node project has the following (simplified) structure:
|models
-index.js
-story.js
-post.js
-app.js
-config.js
This is config.js:
config = {};
config.test = 'test';
config.models = __dirname + '/models';
module.exports = config;
This is story.js:
var config = require('../config.js');
var models = require(config.models);
var foo = {};
foo.bar = 'baz';
var storySchema = mongoose.Schema
({
author: {type: mongoose.Schema.Types.ObjectId},
root: {type: mongoose.Schema.Types.ObjectId, default: null}
});
storySchema.methods.test = function()
{
console.log(foo.bar);
console.log(config.test);
console.log(models);
}
var Story = exports.model = mongoose.model('story', storySchema);
When I create a new Story in app.js and call its test() method, I get this output:
baz (so I know it's seeing objects in the same file)
test (so I know it's seeing variables in the config file)
{} (this "should" log my models object but it logs an empty object, why?)
When I create a new Story object within the story.js file, and run it (node ./models.story.js) the values returned are as expected (the models object is logged rather than an empty object).
Update, here are the index.js and app.js files:
index.js:
module.exports = {
post: require('./post'),
story: require('./story')
};
app.js:
var config = require('./config');
var models = require(config.models);
var story = new models.story.model();
story.test();
I believe the issue is that you've created a circular dependency. Story executes require(config.models) which requires Story again inside index.js.
Rather than storing a string and requireing it everywhere, try storing the models directly in config.models:
config.js
module.exports = {
test: 'test',
models: require(__dirname + '/models')
};
In case anyone runs into this same issue, I wanted to point to a couple resources I came across that helped me resolve the issue. As ssafejava pointed out, the problem does have to do with circular dependency (although ssafejava's solution did not entirely resolve the issue) . What worked for me was designing this dependency out of my application but there are other options if doing so is not possible. See the following issues' comments for a better explanation (in particular, see 'isaacs' comments):
https://github.com/joyent/node/issues/1490
https://github.com/joyent/node/issues/1418

Mongoose Trying to open unclosed connection

This is a simplified version of the problem, but basically I'm trying to open 2 mongodb connections with mongoose and it's giving me "Trying to open unclosed connection." error.
Code sample:
var db1 = require('mongoose');
db1.connect('my.db.ip.address', 'my-db');
var db2 = require('mongoose');
db2.connect('my.db.ip.address', 'my-db');
db2.connection.close();
db1.connection.close();
Any idea how to make it work?
connect() opens the default connection to the db. Since you want two different connections, use createConnection().
API link: http://mongoosejs.com/docs/api.html#index_Mongoose-createConnection
To add on Raghuveer answer :
I would also mention that instead of using mongoose directly (you are probably using it this way you end up on this post) :
require('mongoose').model(...);
You would use the returned connection :
var db = require('mongoose').connect('xxx', 'yyy');
db.model(...);
I get this issue while running my tests.
This is what I did to solve it.
//- in my app.js file.
try {
mongoose.connect('mongodb://localhost/userApi2'); //- starting a db connection
}catch(err) {
mongoose.createConnection('mongodb://localhost/userApi2'); //- starting another db connection
}
I had this problem doing unit test with mocha.
The problem came when I added a second test because beforeEach is called twice.
I've solved this with this code:
const mongoose = require('mongoose');
describe('Your test suite', () => {
beforeEach( () => {
if (mongoose.connection.db) {
return; // or done();
} else {
// connect to mongodb
});
describe('GET /some-path', () => {
it('It should...', () => {
});
});
describe('POST /some-path', () => {
it('It should...', () => {
});
});
});
Hope it helps you!
You are attempting to open the default connection ( which is not yet closed ) a 2nd time.
do the following instead
var db = require('mongoose'); //note only one 'require' needed.
var connectionToDb1 = db.createConnection('my.db1.ip.address', 'my-db1');
var connectionToDb2 = db.createConnection('my.db2.ip.address', 'my-db2');
Using mongoose.disconnect(fn):
mongoose.disconnect(() => {
// here it would be possible "reset" models to fix
// OverwriteModelError errors
mongoose.models = {};
// here comes your logic like registering Hapi plugins
server.register(somePlugin, callback);
});
I found this question typing the error message and despite my problem is a bit different I believe it could be useful for those using Hapi. More specifically Hapi + rest-hapi + mocha.
When running mocha with --watch option I was facing both: OverwriteModelError and Error: Trying to open unclosed connection errors.
Simple Solution -
Use mongoose.createConnection() instead of mongoose.connect()
Its occurs because of version issue

Resources