How to break code in modules in Node.JS? - javascript

I'm with the following code that needs to be used in two files:
var Schema = mongoose.Schema;
var InfoSchema = new Schema ({
name: String,
email: String,
});
var Info = mongoose.model('Info', InfoSchema);
I need use the Info variable in my listTerminal.js, and i need use the InfoSchema in my routes.js .
I'm new in Node.js, and still confuse me a lot the module.exports. Can anyone give me a light?
I was trying to do like this:
module.exports = function() {
var Schema = mongoose.Schema;
var InfoSchema = new Schema ({
name: String,
email: String,
});
};
Them call in my routes.js and listTerminal.js like this:
var mySchema = require('../config/mongo/mySchema');
But is not working, cause in my route.js, i have a route like this:
app.post('/person', function(req, res) {
var Data = {
name: req.body.name,
email: req.body.email
};
var info = new Info(Data);
info.save(function (error, data){
if (error) {
console.log(error);
}
else {
console.log('done');
}
});
});
And the page shows:
Info is not defined
How can i call this mySchema.js in another file??
OBS: if i move the myschema.js code to my route.js file, the route.js will work, but i need separate ;[

Your module should look like this:
var Schema = mongoose.Schema;
var InfoSchema = new Schema ({
name: String,
email: String,
});
module.exports = mongoose.model('Info', InfoSchema);
That way you're exporting the model, not the schema. Then you can use it like so:
var Info = require('../config/mongo/mySchema');
app.post('/person', function(req, res) {
var Data = {
name: req.body.name,
email: req.body.email
};
var info = new Info(Data);
info.save(function (error, data){
if (error) {
console.log(error);
}
else {
console.log('done');
}
});
});

When you do
var mySchema = require('../config/mongo/mySchema');
then mySchema becomes what module.exports is. Since it is a function (in your case) then you have to simply call it:
mySchema();
BTW: I don't know why you defined it as a function. Might not be the best idea.

Related

Turn String into Mongoose Model

I'm learning how to make Mongoose models in Express right now and was wondering if there is a way to convert a string into a matching model.
For instance, if I have a Mongoose model called "User" and a variable like const name = "User", is there a way to convert the string "User" into a User model? Specifically, is there a way to make the following code work?
const name = 'User';
name.findByIdAndUpdate()
Suppose this was the model:
const schema = new mongoose.Schema({ name: 'string' });
const User = mongoose.model('User', schema);
const name = 'User';
Now use the model to construct a document:
const user = new User({ name });
user.save(function (err) {
if (err) return handleError(err);
// saved!
});
or
User.create({ name }, function (err, user) {
if (err) return handleError(err);
// saved!
});
or
const user = await User.create({ name });
Now you can use:
User.findByIdAndUpdate(user.id, { ... }, { ... });
Reference: https://mongoosejs.com/docs/models.html.

How to pass returned function value to ejs

I want to pass the returned function value to ejs engine template but instead I am getting "undefined".
I have file with a couple of functions - util.js, and in that file I have:
var models = require('../../models');
var UserModel = models.user;
var FotoModel = models.photographer;
function whoAmI(req, res){
FotoModel.findOne({
where: {
IdUser: req.user.IdUser
}
}).then(function (foto) {
if(!foto){
return "Client"
}else{
return "Photographer"
}
});
}
module.exports ={
whoAmI: whoAmI,
}
And I have a file named controller.js:
var util = require('../models/util.js');
var exports = module.exports = {}
exports.profile = function(req, res){
res.render("profile", {
name: req.user.Name,
lastName: req.user.LastName,
login: req.user.Login,
email: req.user.Email,
ifClient : util.whoAmI(req, res)
});
}
I would like to send to a variable "ifClient", returned value from function "whoAmI" when rendering the view in ejs. When I am doing like that I'm getting "undefined". How can I do this?

How to get the relation information from 2 collections, nodejs and mongodb

I have 2 schemas (event, venue)
Event Schema is as shown below:
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var EventSchema = mongoose.Schema({
_id:mongoose.Schema.Types.ObjectId,
name:{type:String,unique:true},
venue:[{type:mongoose.Schema.Types.ObjectId, ref:'venue'}],
status:{type:Number, default:0}
});
var Event = module.exports = mongoose.model('Event', EventSchema);
Venue Schema is as shown below:
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var VenueSchema = mongoose.Schema({
_id:mongoose.Schema.Types.ObjectId,
name:{type:String,unique:true},
status:{type:Number,default:0}
});
var Venue = module.exports = mongoose.model('Venue', VenueSchema);
I need the output something as shown below:
[{
event :{
_id:
name:
venue:[{
_id:
name:
}]
}
}]
Please help me refering changes in schema or in nodejs code to populate the same with the one to many relation.
You can achieve this using Populate.
Events.
findOne({ name: 'Casino Royale' }).
populate('venue').
exec(function (err, eventsData) {
if (err) return handleError(err);
console.log('Your data', eventsData);
});

Mongoose findOne() callback returning null

I'm trying to find a user in my node app with mongoose by using
var User = require('../app/models/user');
function mongoTest() {
var publicAddress = "0x8a6be8979340faa30020b0c1f617d8fd4309679f";
User.findOne({"publicAddress": publicAddress}, (err, user) => {
if (err) {
res.status(500).send(err)
} else {
console.log(user);
}
});
}
and err and user always return null. From other questions here (this and this), this usually seems to be related to mongoose pluralising collections. However, I don't think that's my issue because my users.js has
module.exports = mongoose.model('User', userSchema);
// Have also tried module.exports = mongoose.model('User', userSchema, 'User');
For completeness, users.js is
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
// Define the schema for our user model
var userSchema = mongoose.Schema({
local: {
username: String,
password: String,
pictureCaption: String,
publicAddress: String,
contractAddress: String
}
});
Finally, I'm sure that public address exists because I can see it in the mongoDB with Robo 3T.
In your userSchema the publicAddress is part of local object.
var userSchema = mongoose.Schema({
local: {
username: String,
password: String,
pictureCaption: String,
publicAddress: String,
contractAddress: String
}
});
You are trying to find an object with publicAddress but it's actually inside the local object. So you should edit the query as follows to get the result.
User.findOne({"local.publicAddress": publicAddress}, (err, user) => {
if (err) {
res.status(500).send(err)
} else {
console.log(user);
}
});

Mongoose error: Schema hasn't been registered for model when populate

I am trying to join two collections and being able to get the combined data. To do so using Mongoose, i am supposed to use the populate syntax to achieve that. I am receiving error that the Schema Schema hasn't been registered for 'User_Fb'. From my code, I have exported the models and required in my server.js but the error is still appearing. What have I done wrong?
feed_post.model.js
var mongoose = require('mongoose');
var conn_new_app = mongoose.createConnection('mongodb://localhost/new_app');
var User_fb = require('../models/fb_db.model');
var Schema = mongoose.Schema;
var feed_postSchema = new Schema({
user_id: { type: Schema.Types.ObjectId, ref: 'User_Fb' },
content: String,
location: String,
image: [{ type : String }]
});
var Feed_Post = conn_new_app.model('Feed_Post', feed_postSchema);
module.exports = Feed_Post;
fb_db.model.js
var mongoose = require('mongoose');
var conn_new_app = mongoose.createConnection('mongodb://localhost/new_app');
var Feed_Post = require('../models/feed_post.model');
var user_fb = new mongoose.Schema({
name: String,
location: String,
fb_id: Number
});
var User_Fb = conn_new_app.model('User_Fb', user_fb);
module.exports = User_Fb;
server.js
var express = require('express'),
mongoose = require('mongoose'),
User = require('./app/models/user.model'),
Post = require('./app/models/post.model'),
Maptest = require('./app/models/maptest.model'),
Feed_Post = require('./app/models/feed_post.model'),
User_Fb = require('./app/models/fb_db.model'),
app = express();
app.get('/testget', function(req,res){
Feed_Post.findOne().populate('user_id').exec(function(err, c) {
if (err) { return console.log(err); }
console.log(c.fk_user.userName);
});
});
UPDATED from Pier-Luc Gendreau Answer's
fb_db.model.js
module.exports = function (connection) {
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var user_fb = new mongoose.Schema({
name: String,
location: String,
fb_id: Number
});
return connection.model('User_FB', user_fb);;
}
feed_post.model.js
module.exports = function (connection) {
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var feed_postSchema = new Schema({
user_id: { type: Schema.Types.ObjectId, ref: 'User_Fb' },
content: String,
location: String,
image: [{ type : String }]
});
return connection.model('Feed_Post', feed_postSchema);;
}
server.js
var express = require('express'),
app = express(),
mongoose = require('mongoose'),
conn_new_app = mongoose.createConnection('mongodb://localhost/new_app'),
User_Fb = require('./app/models/fb_db.model')(conn_new_app),
Feed_Post = require('./app/models/feed_post.model')(conn_new_app);
app.get('/testget', function(req,res){
Feed_Post.find().populate('user_id').exec(function(err, res) {
if (err) { return console.log(err); }
console.log(res);
});
});
This is all I had to do Customer.findOne({}).populate({ path: 'created_by', model: User }) instead of this Category.findOne({}).populate({'author'})
IF YOU (really) USE MULTIPLE mongoDB CONNECTIONS
I do realise that this is not the case for the OP, but if you genuinely use multiple connections you MUST provide the model when using .populate(), as mongoose will only "find" models on the same connection.
ie where:
var db1 = mongoose.createConnection('mongodb://localhost:27017/gh3639');
var db2 = mongoose.createConnection('mongodb://localhost:27017/gh3639_2');
var userSchema = mongoose.Schema({
"name": String,
"email": String
});
var customerSchema = mongoose.Schema({
"name" : { type: String },
"email" : [ String ],
"created_by" : { type: mongoose.Schema.Types.ObjectId, ref: 'users' },
});
var User = db1.model('users', userSchema);
var Customer = db2.model('customers', customerSchema);
Correct:
Customer.findOne({}).populate('created_by', 'name email', User)
or
Customer.findOne({}).populate({ path: 'created_by', model: User })
Incorrect (produces "schema hasn't been registered for model" error):
Customer.findOne({}).populate('created_by');
The problem is that you are creating a new connection in each and every model, so you end up with a bunch of different connection objects. Even though they are pointing to the same database, mongoose models don't know about other connections. You should instead create the connection object in your main app and then pass it around.
server.js
var express = require('express');
var mongoose = require('mongoose');
var app = express();
var conn_new_app = mongoose.createConnection('mongodb://localhost/new_app');
var Feed_Post = require('./app/models/feed_post.model')(conn_new_app);
app.get('/testget', function(req,res){
Feed_Post.findOne().populate('user_id').exec(function(err, c) {
if (err) { return console.log(err); }
console.log(c.fk_user.userName);
});
});
Then modify your models so they are actually a function:
feed_post.model.js
module.exports = function (connection) {
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var feed_postSchema = new Schema({
user_id: { type: Schema.Types.ObjectId, ref: 'User_Fb' },
content: String,
location: String,
image: [{ type : String }]
});
return connection.model('Feed_Post', feed_postSchema);;
}
Also, like Adrian mentions, you can use mongoose as a singleton. However, I do recommend using createConnection as you did because if you ever need a second connection, you won't have to refactor the connection code to your first database.
It looks like you are creating a different database connection for each model, which isolates the models from each other. Mongoose must assume this isolation, because they could exist on different databases or even database servers.
Try connecting once, and just calling mongoose.model() instead of connection.model() when defining your models. Mongoose is a singleton by default.
In my case, this issue because I haven't included the ref model into the application.
You can get the field you want by using select
Example to get the email of the customer:
Customer.findOne({}).populate({ path: 'created_by', model: User, select: 'email' })
More Details in mongoose documentation

Categories