Structuring a list of favourites with MongoDB & Mongoose? - node.js

I am starting to use mongo, and I would like to create a schema for items that a user has 'favourited'. My current code, using mongoose and node.js looks at follows:
// load the things we need
var mongoose = require('mongoose');
// define the schema for our favourites model
var favouritedItemsSchema = mongoose.Schema({
userId : Number,
item : [{
itemId : Number,
addedDate : Date
}]
});
// create the model for favourites and expose it to our app
module.exports = mongoose.model('Favourites', favouritedItemsSchema);
Coming from a relational DB background, I am wondering whether the above approach would represent a suitable NoSQL DB design approach? If not, can someone show me what would be something that fits the design philosophy?

Yes, you are right, the relational and the NoSQL design approach are totally different.
Where you have 10 tables for example in RDBMS, you could have only 2 or 3 collections in mongo. That's because the way we create relations between objects is far more interesting in NoSQL (subdocument, arrays, etc..).
Here is one solution for your problem, reusing an existing User collection.
// load the things we need
var mongoose = require('mongoose');
// define the schema for our model
var userSchema = mongoose.Schema({
username: string,
favourites: [{
id: Schema.Types.ObjectId,
addedDate: Date
}]
});
// export model
module.exports = mongoose.model('User', userSchema);

Related

How to associate a mongoose model with the right MongoDB collection in Express.js app?

how to point to particular collection in mongodb using mongoose ORM in express js app .
NA
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var personSchema = new Schema({
name: String,
age: Number
});
module.exports = mongoose.model('person', personSchema);
consider my mongo database have multiple collection ,so how will my above code will point to particular collection.
I'm really sorry my selected answer is not accurate. I can't delete it because it is accepted. The accurate answer to your question is, mongoose.model('person', personSchema); will automatically create a plural lower case version of the model name.In this case, it will automatically create a collection persons in mongoDB if it doesn't exist already.
If you want to override this default behavior, you can do it like this:
var personSchema = new Schema({
name: String,
age: Number
},
{
collection:'people'
});
or
mongoose.model( 'person', personSchema, 'people' ) so you refer to it as person, but collection name will be people
Usually we follow convention of naming the collection plural in mongoDB. For example in MongoDB, we create users table, but use singular in Node.js. So the exports would be:
module.exports = mongoose.model('users',UserSchema)
And in other script, we require it as follows:
const User=require('<pathToModel>/user')
This means we are referring to the model as User, it is based on UserSchema and the collection associated with this is users
In your code, you could do this:
module.exports = mongoose.model('person', personSchema);
If you have a specific collection you want documents based on a specific model to go into, you can use mongoose.model('person', personSchema, collection).
Or, you could name the desired associated collection in the Schema definition:
var dataSchema = new Schema({..}, { collection: 'data' });
https://mongoosejs.com/docs/guide.html

How to show relationship between schemas in mongodb like in sql database?

I have got two models one is "Posts" and another one is "Comments". I want to show relationship between these two models which is a single post has may comments, but i am stuck here. I know how to show these kind of relationship in sql database. Currently i am using mongoose-schema and node js.
To make relation in between Posts and Comments schema
// Comments Schema
var CommentSchema = new Schema({
// your fields
});
module.exports = mongoose.model('Comments', CommentSchema);
// Post schema
var PostSchema = new Schema({
// your fields
comments:[{
type: Schema.Types.ObjectId,
ref:'Comments'
}],
});
// so in comments you will store comments._id values
module.exports = mongoose.model('Posts', PostSchema);

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);
};

One-To-Many relation in MongoDB

At the moment I am looking at mongoDB. I try to implement a simple one-to-many relation using nodejs and mongoose:
Model/Schema User:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var UserSchema = new Schema({
name: String
});
module.exports = mongoose.model('User', UserSchema);
Model/Schema Article:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var ArticleSchema = new Schema({
name: {
type: String,
required: true
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
module.exports = mongoose.model('Article', ArticleSchema);
So my question, now:
How can I get all Users including its Articles?
Do I really have to add a ref to my UserScheme, too? What is the best-practice in an one-to-many relation like this? Is there something like a join in mongodb?
One User has many Articles - an Article belongs to one User.
Calling something like /user/:user_id , I want to receive the user with _id=user_id containing all of his articles.
That is the most horrible idea, for various reasons.
First, there is a 16MB BSON document size limit. You simply can not put more into a document. Embedding documents is rather suited for "One-to-(VERY-)Few" relationships than for a "One-to-Many".
As for the use case: What is your question here? It is
For a given user, what are the articles?
REST wise, you should only return the articles when /users/:id/articles is GETed and the articles (and only the articles) should be returned as a JSON array.
So, your model seems to be natural. As for the user:
{
_id: theObjectId,
username: someString
…
}
and an article should look like this:
{
_id: articleIdOrSlugOrWhatever,
authors: [theObjectId],
// or author: theObjectId
retention: someISODate,
published: someOtherISODate
}
So when your REST service is called for /users/:id you'd simply look up
var user = db.users.findOne({_id:id})
And when /users/:id/articles is called, you'd lookup
var articles = db.articles.find({author:id})
Problem solved in a scalable way, adhering to REST principles.

Mongoose schemas and collections

Hi everyone this is the first time I ask a question in here,
I'm very new into the MEAN stack and by now I'm trying to develop an application using it. As I understand in mongodb an Schema (Database) can have one or more collections (Tables(?)), when I'm using mongoose I define a Song model and an Artist model:
For Song:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var songSchema = new Schema({
songName: { type: String },
songArtist: [{type : Schema.Types.ObjectId, ref : 'Artist'}]
});
module.exports = mongoose.model('Song', songSchema);
For artist:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var artistSchema = new Schema({
artistName: { type: String }
});
module.exports = mongoose.model('Artist', artistSchema);
My app.js looks like this:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/song', function(err, res) {
if(err) throw err;
console.log('Connected to Database');
});
var models = require('./models/song')(app, mongoose);
The issue with this is, as I understand and saw, that I'm creating 2 databases/schemas while I want to Create one database/schema and have this two collections in there:
SongDatabase:
--- Song
--- Artist
How should I do it in this case with my mongoose models/controllers and my app.js? Thanks in advance :)
I solved all my doubts taking a look into this tutorial, as you can see in here they implement two collections within one database (My inicial concern). Once you are connected to the database and you perform a post to the collection you want, in this case thread or post, it will create the collection into mongodb.
The issue there is that your connection string is mongodb://localhost/song
Song becomes your DB, and within Song you should be able to see two collections
- SongS
- ArtistS
Posible solutions: Flush the database, drop all. Start clean and check what your application is doing. Use another name for the DB

Resources