I am creating an app with mongoose and express.I have user and venue models.
I want users to follow venues and view all the venues they are following. I also want to display all users following a venue on the venue's page. A user follows many venues and a venue has many user followers.
What is the best way to implement this relationship with the mongoose ORM? What should my models look like? What about the CRUD following operations?
I have seen mongoose-relationship but it does not seem very popular. What is the mongoose.js community solution to implementing this "following" database relationship?
the user model/Schema will have an "venuesFollowing" array containing venue._id's. The venue model/Schema will have a "usersFollowing" array containing user._id's.
var Mongoose = require('mongoose');
var Schema = Mongoose.Schema;
var Venue = require('./venue');
var userSchema = new Schema({
fullName: {type: String, required: true},
username: {type: String, required: true},
email: {type: String, required: true},
venuesFollowing: [{type: Mongoose.Schema.ObjectId , ref: 'Venue'}],
});
var User = Mongoose.model("User", userSchema);
module.exports = User;
You can use this user model as a basis to construct your venue model and substituting the venuesFollowing with users following. You are requiring the Venue model so that it can be referenced in this user model and vice-versa. You will be able to access all of the users following a venue by their ID's and vice-versa for the the users and the venue id's that they follow.
Related
I am completely new to Node.js and Mongoose and I came up to this problem of having
Event and User and a relationship where the User can go to any Event and Event can have many participating users.
Any time the user would want to attend an Event I could add the Event id to User's array of events and simultaneously add the User to the Event's array of users but I think that I want to avoid this approach because I would store the same information twice.
On the other hand I could only store the User to the Event's array of users and use virtual mapping to retrieve all the User's events but I find this approach quite time consuming. It seems to me that I would have to go through each Event and then through all of its participating users to find out if the user really is participating or not. Anyways if there is a way to do this using the virtual function, i don't know how to map the localField: userId to the array of the Event's foreignField: participants.
What would be the correct approach to this problem?
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const eventSchema = Schema({
name: String,
user: [{ type: Schema.Types.ObjectId, ref: 'User' }]
});
const userSchema = Schema({
name: String,
event: [{ type: Schema.Types.ObjectId, ref: 'Event' }]
});
const Event = mongoose.model('Event', eventSchema);
const User = mongoose.model('User', userSchema);
use can read more here https://mongoosejs.com/docs/populate.html
I want to use mongodb on my new project. That is first time, im using mongodb. In relational databases i was saving datas like:
tbl_country > id,name,created_at,etc..
tbl_city > id,country_id,name,created_at,etc...
tbl_user > id,name_surname,city_id,etc...
In this schema i can find a city's country, a user's country, etc... via using foreign keys.
Which way do you suggest to create a schema like this in best performance by nodejs w/ mongodb ?
You can still use foreign keys when you create your schemas. Please check this schemas as examples you have given.
var CountrySchema = new Schema({
name: String,
created_at: Date
});
var CitySchema = new Schema({
countryName: { type: mongoose.Schema.Types.ObjectId, ref: 'Country' },
created_at: Date
});
var UserSchema = new Schema({
name_surname: String,
city: { type: mongoose.Schema.Types.ObjectId, ref: 'City' }
})
mongoose.model('Country', CountrySchema);
mongoose.model('City', CitySchema);
mongoose.model('User', UserSchema);
and when you fetch data, you have to use 'populate' method. For instance:
City.find()
populate('countryName', 'name') // It will bring only name field
.exec(function(err, cities) {
})
Btw. _id s are automatically created by mongo for each data. So you do not need to add id field into your schemas. Hope it helps. Good luck
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.
I am trying to teach myself node.js, coming from Rails, and I want to establish this relationship:
A group has_many users, a user belongs_to group
How would I go about doing this in my models?
//for user
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
name: String
});
module.exports = mongoose.model('User', UserSchema);
//for group
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var GroupSchema = new Schema({
name: String
});
module.exports = mongoose.model('Group', GroupSchema);
Also I would like to allow a moderator to kick someone out of a group if the person were obnoxious. How could I target a user belonging to a group and then delete the user. It seems more complicated than the traditional CRUD methods. Do I need nested resources like in rails, or the equivalent?
Mongoose has a feature called population that you can use to set up "relationships" (MongoDB only has limited support for relationships).
Your schema would look something like this:
var UserSchema = new Schema({
name : String,
group: { type: Schema.Types.ObjectId, ref: 'Group' }
});
var GroupSchema = new Schema({
name : String,
users : [ { type: Schema.Types.ObjectId, ref: 'User' } ]
});
In other words: the User model has a group property which points to the group the user belongs to, and the Group model has a users property (an array) that contains references to the users that belong to the group.
To associate a user to a group (assuming that group is a variable that is a Group instance):
user.group = group;
user.save(...);
And to add the user to a group:
group.users.push(user);
group.save(...);
However, you should be aware that array properties in MongoDB documents have limited scalability. I think that a few dozen items in an array will work just fine, but when the number of users in a group are expected to be in the thousands, this probably won't be a viable solution. In that situation, you probably should consider a "junction collection" (similar to SQL's "junction table").
To remove a user from a particular group, I think you need to use .update():
Group.update({ _id: group._id }, { $pull : { users : user._id }})
I am a bit confused by something in MongoDB, when using Mongoose, since I am new to it. I have two collections: authors and posts.
each author in the authors collection have the mongodb inbuilt id associated with them, which as per my understanding is of the schematype/datatype Objectid.
Now in my posts collection, I have a field which has is called author, which should have the value of the author's Objectid, similar to the foreign key concept in SQL.
My question is, which schematype/datatype should I declare the author field in the posts collection? Should I put it as Objectid? If so, would it not auto-increment and not be settable?
Mockup Of Schemas:
var authors = new mongoose.Schema({
name: String,
email: String
});
var posts = new mongoose.Schema({
title: String,
author: **??**
});
Any help would be hugely appreciated!
You can use population for that:
var authors = new mongoose.Schema({
name: String,
email: String
});
var posts = new mongoose.Schema({
title: String,
author: { type: Schema.Types.ObjectId, ref: 'Author' }
// assuming the model will be called 'Author'
});
To use:
// Get 'author' some how (create a new one, query the
// database for existing authors, etc);
...
// Create a new post and associate it with 'author' by referencing its `_id`:
var post = new Post({
...
author : author._id
});
post.save(...);
The documentation linked above also shows how you can get Mongoose to automatically retrieve the author document when you're querying posts.