MongoDB (Mongoose) make array part of schema - javascript

I'm creating a chat application with MongoDB (mongoose) and Nodejs. As you see below I have a schema as mongoose allows but my users in storeSchema needs to be an array of Strings (usernames). Is this the proper way to do it?
"use strict";
var express = require('express');
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
user: String
});
var messageSchema = new mongoose.Schema({
msg: String
});
var storeSchema = new mongoose.Schema({
users: [userSchema], // needs to be an array of users
channels: {
general: {
messages: [messageSchema]
},
videogames: {
messages: [messageSchema]
},
programming: {
messages: [messageSchema]
},
other: {
messages: [messageSchema]
}
}
});
var User = mongoose.model('User', userSchema);
var Message = mongoose.model('Message', messageSchema);
var Storage = mongoose.model('Storage', storeSchema);
module.exports = {
User: User,
Message: Message,
Storage: Storage
}

If you want users to be an array of username strings, then define it in storeSchema as:
users: [String]

Related

Passaport-Local-Mongoose: How do i allow identical usernames

I'm using Passport Local Mongoose to create a user on my database. My goal is to allow users with the same username to register into my app. On my research, i found that if i pass an object as option on my Schema.plugin with 'usernameUnique: false', i would allowed users to register with the same username. The only problem is when a try it to make a register, i get an "UserExistsError" on my console.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');
const UserSchema = new Schema({
email: {
type: String,
required: true,
},
username: {
type: String,
required: true,
unique: false
},
});
const options = {
usernameUnique: false,
}
UserSchema.plugin(passportLocalMongoose, options);
const User = mongoose.model('User', UserSchema);
module.exports = User;

How to populate using mongoose? I have a problem

I'm making a simple example of CRUD for a larger and open source project. Right now I want to populate with user data, I have already looked at the documentation and some forums and I am not able to solve the problem that is causing here.
The message in terminal "Populated User undefined"
Could anyone help?
userModel
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
name: {
type: String
},
});
userController
var mongoose = require('mongoose'),
User = mongoose.model('Users');
exports.create_a_user = function(req, res) {
var new_user = new User(req.body);
new_user.save(function(err, user) {
if (err)
res.send(err);
res.json(user);
});
};
msgModel
module.exports = mongoose.model('Users', userSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var msgSchema = new Schema({
title: {
type: String
},
body: {
type: String
},
created_date: {
type: Date,
default: Date.now
},
user : {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
});
module.exports = mongoose.model('Messages', msgSchema);
msgController
var mongoose = require('mongoose'),
Message = mongoose.model('Messages');
exports.list_all_messages = function (req, res) {
Message.find({})
.populate('user')
.exec((err, msg) => {
if (err)
res.send(err);
res.json(msg);
});
};
module.exports = mongoose.model('Users', userSchema);
maybe in msgSchema you have to reference 'users' instead of 'user'
So, I found the error in the code, in the user's schema there was a lack of reference to the export of the name that was placed in the user's model.
user : {
type: mongoose.Schema.Types.ObjectId,
ref: 'Users'
},
So,...
module.exports = mongoose.model('Users', userSchema);

Add new mongoDB document with object type

I'm totally new to mongoDB, just coming from MySQL, so I'm trying to add a new document to a mongo database in Node.js, I have the code working except when I have to include a custom object.
Here's my code:
router.post('/', async (req, res) => {
const book= new Book({
title: req.body.book.title,
year_published: req.body.book.year_published,
author: req.body.author // ==> here is the problem without it works fine (comes the full author via body parameter)
});
try {
const savedBook = await book.save();
res.json({
insertedBook: savedBook
});
} catch (err) {
//console.log("Error:" + err);
res.json({error: err});
}
});
The book and author models (simplified):
// ======= AUTHORS ================ //
var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate-v2');
const schema = new mongoose.Schema({
name: {
type: String,
required:true
},
place_birth: {
type: String,
required:true},
});
schema.plugin(mongoosePaginate);
const Authors = mongoose.model('Authors',schema);
module.exports = Authors;
// ======= BOOKS ================ //
var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate-v2');
var ObjectId = mongoose.Schema.Types.ObjectId;
const schema = new mongoose.Schema({
title: {
type: String,
required:true
},
year_published: {
type: String,
required:true},
author: [{
type: ObjectId,
ref: 'Authors',
required:false
}],
});
schema.plugin(mongoosePaginate);
const Books = mongoose.model('Books',schema);
module.exports = Books;
Data posting:
{
"book": {
"title": "Entrada con cuernos",
"year_published": "2020",
},
"author": {
"name": "Marcus",
"place_birth": "Moscow",
}
}
What's the proper way to insert a book document?
Thanks
When creating a new Book, Book.author should be a mongoose document, meaning the Author should exist in the mongoDB already.
You need to first save the Author in the DB, then pass it in Boot.author with it's Author._id property set
P.S.: Use singular words when describing your collections:
const Authors = mongoose.model('Authors',schema);
const Authors = mongoose.model('Author',schema); // recommended
mongoose will take care of the plural naming
The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural, lowercased version of your model name

How to fetch data from mongodb using nodejs, expressjs

Here is my code
file name student.js
var mongoose = require('mongoose');
var studentSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
rollno:{
type: Number,
required: true
},
grade:{
type: String,
required: true
},
result:{
type: String,
required: true
}
});
var Student = module.exports = mongoose.model('Student',studentSchema);
module.exports.getStudents = function (callback){
Student.find(callback);
}
**filename app.js**
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var PORT= process.env.PORT || 3000;
Student = require('./models/student');
mongoose.connect('mongodb://localhost/register');
var db= mongoose.connection;
app.get('/api/student', function (req,res){
Student.getStudents(function (err, student){
if(err){
throw err;
}
res.json(student);
});
});
app.listen(PORT);
console.log('Running app on port:' + PORT);
If you have an existing collection that you want to query using Mongoose, you should pass the name of that collection to the schema explicitly:
var studentSchema = new mongoose.Schema({ ... }, { collection : 'student' });
If you don't, Mongoose will generate a collection name for you, by lowercasing and pluralizing the model name (so documents for the model Student will be stored in the collection called students; notice the trailing -s).
More documentation here.

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