Issue with MongoDB, Node and Express-looking up ID in Mongo - node.js

I am currently working on a simple MEAN project and I am working on pulling one item out of my mongo db and show it on the web page. Whenever I go to the site
http://localhost:3000/api/events/5782b1dbb530152d0940a227 to see the information on the object, I get null displayed. I am, like I said, suppose to see information on this object. Here is what my code looks like:
controllers:
var mongoose = require('mongoose');
var Eve = mongoose.model('Info');
var sendJSONresponse = function(res, status, content) {
res.status(status);
res.json(content);
};
module.exports.eventsReadOne = function(req, res) {
Eve
.findById(req.params.eventid)
.exec(function(err, info){
sendJSONresponse(res, 200, info)
});
//sendJSONresponse(res, 200, {"status" : "success"});
};
Models:
var mongoose = require( 'mongoose' )
var eventSchema = new mongoose.Schema({
activity: String,
address: String,
});
mongoose.model('Info', eventSchema);
routes:
var express = require('express');
var router = express.Router();
var ctrlEvents = require('../controllers/events');
//events
router.get('/events/:eventid', ctrlEvents.eventsReadOne);
module.exports = router;
Now, one thing that may be noticed is that I call my mongo collection events. However, I forgot that event is a key word in JS so I tried "changing" it to Info which you will see on the last line of my model. Like I said, if I go to the site http://localhost:3000/api/events/5782b1dbb530152d0940a227, where the last number is the obj _id then I should see all of the data on it. Instead, all that I see is null. Any help would be great, thank you!
my other model file, db.js, has the connection:
var mongoose = require('mongoose');
var dbURI = 'mongodb://localhost/mission';
mongoose.connect(dbURI)
require('./events');

Mongoose will use the model name to determine which MongoDB collection it should use. The default scheme is to take the model name, lowercase and pluralize it, and use the result as the collection name, which in your case (using Info as model name) would be infos:
// This is where the model is created from the schema, and at this point
// the collection name is decided.
mongoose.model('Info', eventSchema);
If you want it to use a different collection, you have to explicitly tell Mongoose what collection to use by setting the collection option for your schema:
var eventSchema = new mongoose.Schema({
activity : String,
address : String,
}, { collection : 'events' });
To fix the error you're stating in the comments (Schema hasn't been registered for model "mission"), you need to make sure that you change all occurrences of mongoose.model():
// To create the model:
mongoose.model('Mission', eventSchema);
// Later on, to access the created model from another part of your code:
var Eve = mongoose.model('Mission');
(although it seems to be that "mission" is the name of your database; because your collection is called events I would think that a model name Event seems much more appropriate)

Related

How to combine models using Mongoose Population

At the moment I'm defining different models in different files depending on where I use them but there are relations between them and I find myself constantly fetching one, then the other using an ID from the first. E.g.:
File 'models/users.js'
var mongoose = require('mongoose');
var db = mongoose.connection;
var UserSchema = mongoose.Schema({
// fields
companyId: {
type: String
}
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
File 'models/company.js'
var mongoose = require('mongoose');
var db = mongoose.connection;
var CompanySchema = mongoose.Schema({
// fields
});
// module export and functions etc.
So in that example the User companyId is the ID of one of the companies. Then in my routes I'll import both models, get a User, find the company ID and then fetch that company data:
var Promise = require('bluebird');
var User = Promise.promisifyAll(require('../models/user'));
var Company = Promise.promisifyAll(require('../models/company'));
User.getUserByIdAsync()
.then(function(user){
return [user, Company.getCompanyByIdAsync(user.companyId)];
}).spread(function(user,company){
// Do stuff
}).catch(function(err)... etc });
I've been reading about population on the Mongoose docs here: http://mongoosejs.com/docs/populate.html but in the examples everything is in one file. I'm trying to keep models separate for maintainability (and my sanity) so any calls to other models will throw errors.
Is there a way to join the models or reference other external models so I can do this? Is the schema even right?...
I'm using Express and Mongoose.
For reference, the fix is pretty simple. The models being in different files makes no difference.
Change the user model so that the data type is an ObjectID and the ref field references the correct model like so:
companyId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Company'
}
And use it:
User.find({}).populate('companyId').exec(callback);
Really simple in the end..
You can save company reference in Users Model and hence While fetching details you can get company details as well :
var getUserWithPopulate = function (criteria, projection, options, callback) {
Models.Users.find(criteria, projection, options).populate([
{path: 'company', select:'companyId, companyName'}
]).exec(callback);
};

Mongoose findById is returning null

So I have this schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TreeSchema = new Schema({
}, { collection: 'treeLocations' });
var TreeDetailsSchema = new Schema({
}, { collection: 'treeInfo' });
module.exports = mongoose.model('Tree', TreeSchema);
module.exports = mongoose.model('TreeDetail', TreeDetailsSchema, "treeInfo");
And I am calling by ID like this:
var TreeDetails = require('./app/models/tree').model('TreeDetail');
router.route('/api/trees/:tree_id')
.get(function(req, res) {
TreeDetails.findById(req.params.tree_id, function(err, treedetail) {
if (err)
res.send(err);
res.json(treedetail);
});
});
For some reason - http://localhost:3000/api/trees/5498517ab68ca1ede0612d0a which is a real tree, is returning null
Something that might help you help me:
I was following this tutorial: https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
The only thing I can think of that changed is that I have a collection name. Might that be it?
The step that I don't see is how you actually connect to MongoDB and after that, how you get the Model from the connection.
// connect to MongoDB
var db = mongoose.createConnection('mongodb://user:pass#host:port/database');
// now obtain the model through db, which is the MongoDB connection
TreeDetails = db.model('TreeDetails');
This last step is how you associate your model with the connected mongo database.
More info on Mongoose.model
There are several ways to establish a connection to MongoDB with mongoose, the tutorial uses:
mongoose.connect('mongodb://node:node#novus.modulusmongo.net:27017/Iganiq8o');
(Personally I prefer the more explicit mongoose.createConnection as shown in the example)
(I used mongoose 4.3.1 for this example)
My steps to reproduce, in order to provide a working example (without creating a webservice for it):
var mongoose = require('mongoose'),
TreeDetails, db;
// create the model schema
mongoose.model('TreeDetails', mongoose.Schema({
// .. your field definitions
}, {collection: 'treeInfo'}));
db = mongoose.createConnection('mongodb://user:pass#host/example');
TreeDetails = db.model('TreeDetails');
TreeDetails.findById('5671ac9217fb1730bb69e8bd', function(error, document) {
if (error) {
throw new Error(error);
}
console.log(document);
});
Instead of:
var TreeDetails = require('./app/models/tree').model('TreeDetail');
try:
var mongoose = require('mongoose'),
TreeDetails = mongoose.model('TreeDetail');
Defining the collection name shouldn't give you any issues. It's just what the collection will be called in the database / when using the mongo shell.
And just to be sure, try logging req.params.tree_id before calling findById to make sure it's coming through as you suspect.

express mongoose router query

Am trying to return all item with store name ,using the conditional query method ,but the it return all items insteads ,i tried the maybe my logic is wrong
because what am trying to achieve it return all data that where store name is ,is say max mart
route('api/discount/?store=storename)
and
router.route('/discount/:store')
.get(function(req,res){
Discount.find({store:req.params.store}, function(err, discount){
if (err)
res.send(err);
res.json(discount);
});
})
so i called api/discount/store ,but this return all the data ,does not make any queries
schema model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var DiscountSchema = new Schema({
store: String,
location : String,
discount : Number,
});
module.exports = mongoose.model('Bear', DiscountSchema);
You made a wrong query. You have a route to /discounts/:discount_id and you query for store:req.params.store, and a req.params.store doesn't exists, just a discount_id

Mongoose referencing models in other models

I am working on an express/node app, using mongodb and mongoose to model users, players, teams, etc. Between these models I am using references with ObjectIDs, so between players and teams there is a connector model RosterSpot which holds a team_id and player_id, both with the Schema type of ObjectID.
Anyways, I am running into problems trying to reference RosterSpots inside of the Team and Player models. I would like to have a method for Players that grabs all their teams, and vice versa for Teams. First, given this code in roster_spot.js
// Synchronously load model dependecies, so foreign model calls can be made
var fs = require('fs');
var models_path = __dirname;
fs.readdirSync(models_path).forEach(function (file) {
if (~file.indexOf('.js')) require(models_path + '/' + file);
})
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
var Team = mongoose.model('Team');
var Player = mongoose.model('Player');
var RosterSpotSchema = new Schema({
team_id: {type: ObjectId, required: true},
player_id: {type: ObjectId, required: true}
});
....
RosterSpotSchema.statics.getTeamsForPlayer = function(player_id, callback) {
this.getTeamIdsForPlayer(player_id, function(ids){
Team.find({ _id: { $in: ids } }, function(err, teams){
callback(teams);
});
});
};
...
this works perfectly fine, as this RosterSpot model calls the Team.find() and Player.find() methods without a problem.
The problem comes when I try to make that call in the Player or Team model in the following method in player.js:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var RosterSpot = mongoose.model('RosterSpot');
var PlayerSchema = new Schema({...});
...
PlayerSchema.methods.getTeams = function (callback) {
RosterSpot.getTeamsForPlayer(this._id, function(teams){
callback(teams);
})
};
When I have the var RosterSpot = mongoose.model('RosterSpot'); in there, it throws a "MissingSchemaError: Schema has not been registered for 'RosterSpot'."
I've tried loading in the models via require and async stuff but nothing is working.
The crazy thing is, though, that I've been able to call these sorts of methods for users and players, using the connector model Family and that all works fine. I don't even have to initialize a variable for Family in users.js, which is weird but it works...
I have thought that maybe it is my testing environment that might mess with loading files, but when I start the server it also throws that error. Would be helpful to know if this is even possible, and any insight to this problem would be much appreciated.

What does the connect command do when using Mongoose (using it in a node.js environment)?

I'm new to mongoose and am having trouble starting out. All I want to do is store some values, and retrieve all values. Right now, I'm just trying to get a base example working. Here's my code right now:
var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://localhost/my_database');
var Schema = mongoose.Schema;
var IPhoneDevice = new Schema({
fbId : { type: String }
, deviceToken : { type: String }
});
var IPhone = db.model('IPhone', IPhoneDevice);
var u = new IPhone();
u.fbId = 'John';
u.save(function(){
log.debug("Saving");
});
IPhone.find({}).all(function(array){
log.debug("Finding stuff");
});
The problem is, it never prints out anything. I think it might be something to do with the mongoose connect line. I just copied this from an example, but does there need to be a file on my localhost where the database is stored? I don't have any file called my_database anywhere...do I need to create one?
I would write the last call like this:
IPhone.find({}, function (err, docs) {
console.log(docs);
});
mongoose needs the query in the find, then a callback to handle the returned documents or the error.
See: Finding Document with Mongoose

Resources