Should I have different collections for different users in mongodb? - mongodb

Im new to databases and mongo. I'm creating a web app that has different types of users that have access to different routes via different UI's. eg: user, company, admin. My question is should I create a single collection that houses all users and simple add a "user-type" or "access-level" as a property on each User object? or should I have 3 different Collections, one for each type of user?
What is common practice for this type of thing?

What would be fields for each type of user? If they are same, use user type option. Same user can be in multiple roles tomorrow. Storing in same collection would be better.
If the fields to be stored are completely different, and there is not a chance that same user can be in 2 roles ever in your application, use 3 collections.

By your question your Schema can have Roles set as ENUM and value as user, company, admin. and role should be accordingly set while you save the data to db
var UserSchema = new Schema({
first_name: {
type: String,
required: true
},
last_name: {
type: String
}, Roles: {
type: String,
enum: ['USER', 'COMPANY', 'ADMIN'],
default: 'ACTIVE'
}
});
UserSchema.index({
username: 1,
role: 1
});

Related

Database design - saving the entire object to a user or just the id of an object?

database noob here using MongoDB, in my program, I have users, and the core of my program are these roadmaps that I display. So, each user can create roadmaps, save others roadmaps, blah blah... Each user has a field named savedRoadmaps and createdRoadmaps which should store the roadmaps. My question is, should I just store the roadmap _ids in the savedRoadmap and createdRoadmaps field or the entire roadmap?
I am asking this because it feels like saving just the _id of the roadmaps can save storage, but it might not come in handy when I have to fetch the data of the user first, then fetch the roadmap using the roadmap ID in the user's savedRoadmap/createdRoadmap field, versus just fetching the user and the savedRoadmap field will already have the roadmap in there.
And btw, is there any sweet and brief database design read out there, please direct me to some if you know any!
For a user, I want it to have a name, email, password, description ofcourse, and also savedRoadmaps and createdRoadmaps. A user can create unlimited roadmaps and also save as much as he or she wants. For a roadmap, I want it to have a name, category, time_completion, author, date, and a roadmap object which will contain the actual json string that I will use d3 to display. Here's my User and Roadmap Schema right now:
const RoadmapSchema = new Schema({
author: {
type: String,
require: false
},
name: {
type: String,
require: true
},
category: {
type: String,
require: true
},
time_completion: {
type: Number,
require: true
},
date: {
type: Date,
default: Date.now
},
roadmap: {
type: "object",
require: true
}
});
and User Schema:
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
savedRoadmap: {
type: "object",
default: []
},
createdRoadmap: {
type: "object",
default: []
}
});
My question is, inside of the savedRoadmap and createdRoadmap fields of the User schema, should I include just the _id of a roadmap, or should I include the entire json string which represents the roadmap?
There are 3 different data-modeling techniques you can use to design your roadmaps system based on the cardinality of the relationship between users and roadmaps.
In general you need to de-normalize your data model based on the queries that are expected from your application:
One to Few: Embed the N side if the cardinality is one-to-few and there is no need to access the embedded object outside the context of the parent object
One to Many: Use an array of references to the N-side objects if the cardinality is one-to-many or if the N-side objects should stand alone for any reasons
One-to-Squillions: Use a reference to the One-side in the N-side objects if the cardinality is one-to-squillions
And btw, is there any sweet and brief database design read out there,
please direct me to some if you know any!
Rules of Thumb for MongoDB Schema Design: Part 1

sailsjs one-way associations confusion

I am having a hard time wrapping my head around associations with sailsjs.
I have 2 models
Services
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
model: 'users',
via: 'id',
},
},
Users
attributes: {
email: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string'
}
},
So, a service is tied to a user (matching the id of the user).
I used to do a call like http://localhost:1337/Services?userId=userId
Now I would like to transition to associations using the above model attributes.
This works by calling the ID of the service just fine (it includes the users data as well), however if all i have is the user, how could I get the service
Doing the same call (http://localhost:1337/Services?userId=userId) returns and empty object.
Am I forced to actually have a one-to-one or one-to-many association? I don't understand why I can no longer use the userId field (stored in the DB) to do queries once I start using associations. I guess I am looking for the best of both worlds here.
EDIT:
Let me try make this more clear. Before trying to do associations, I could call this URL (using blueprint)
http://localhost:1337/Services?userId=userId
The Services model used to look like this
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
type: 'string',
required: true,
},
},
Then when a user is created, a service for that user is created with the userId matching the ID in the Users table.
Now I would like to implement associations using the above model scheme.
However, because (my best guess) the userId field of the service is mapped to the Users model, I am unable to search for a Server using the userId field that is stored.
I hope that makes sense? In another words, tryin to call
http://localhost:1337/Services?userId=userId
returns nothing when using associations but does return a value when I don't use associations

How to define a collection for User Roles and User Details in Mongodb?

In mysql; I have a two tables named User Roles and User details. Role ID using as foreign key in User details table. How to convert this in Mongodb?
You can have that in same way.I used to follow same pattern
Role schema-
var rolesSchema = new mongoose.Schema({
'role_name':{type:String},
'actions':[{type:String}]
})
User Schema -
var userSchema = new mongoose.Schema({
first_name : String,
last_name : String,
role: String, // OR { type: mongoose.Schema.Types.ObjectId, ref: 'role'}
})
and you can directly use populate of mongoose to fetch role data for this user or manually check it using role as string.
First you need to understand the fundamental structure of schema and its definition in mongodb and how it shall translate from mysql.
Let us see few defintions
if you have two tables as you've given, user roles and user details, your potential mongodb schema shall be as follows
{
_id: objectid ("random alphanumeric"),
username: "John Doe",
firstname: "John",
lastname: "Doe",
title: "Manager",
Role: [
{
id: "Random alphanumeric",
type: "Admin"
}
]
}
Please also go through the Mongodb documentation for sql db mapping
https://docs.mongodb.org/manual/reference/sql-comparison/
Note: here _id refers to your user id.

Database Scheme for unified profiles fetched from multiple Social Networks (Facebook and Linkedin...)

The application I'm building allows users to login using both their Facebook and Linkedin Accounts in order to fetch their friend from these networks.
Each of their friend can be a user of the application.
I have a couple of problems to solve:
How should I structure my Database Schema?
How do I unify profiles?
Potential Solutions
Regarding the structure:
I'm using mongo (But am open to suggestions). So I though that i'd create a collection of Users where each user document looks like this:
User = {
appId: <id>,
connections: [userId]
}
So, each user has:
A unique app generated id (could be the doc's id for simplicity).
An array of user's IDs. The IDs of their Friend's profiles created in my app.
Regarding Unifying profiles:
Should I unify users based on their email or name? or both?
Misc
I though that I could use LoginRadius but i was using singly just for that, and then they suddenly decided to kill the service. In other words, I don't want to depend on a third party tool because this is a core feature.
var UserSchema = new Schema({
name: { type: String, default: '' },
email: { type: String, default: '' },
provider: { type: String, default: '' },
hashed_password: { type: String, default: '' },
salt: { type: String, default: '' },
authToken: { type: String, default: '' },
facebook: {},
linkedin: {}
})
I'm using the Schema mentioned above for my users collection.
and when a new user wants to Sign up, using either the local strategy or social strategies
I just use the update mongoose function with the "upsert: true" option, to either update or
create an entry.

Node.js - Mongoose/MongoDB - Model Schema

I am creating a blog system in Node.js with mongodb as the db.
I have contents like this: (blog articles):
// COMMENTS SCHEMA:
// ---------------------------------------
var Comments = new Schema({
author: {
type: String
},
content: {
type: String
},
date_entered: {
type: Date,
default: Date.now
}
});
exports.Comments = mongoose.model('Comments',Comments);
var Tags = new Schema({
name: {
type: String
}
});
exports.Tags = mongoose.model('Tags',Tags);
// CONTENT SCHEMA:
// ---------------------------------------
exports.Contents = mongoose.model('Contents', new Schema({
title: {
type: String
},
author: {
type: String
},
permalink: {
type: String,
unique: true,
sparse: true
},
catagory: {
type: String,
default: ''
},
content: {
type: String
},
date_entered: {
type: Date,
default: Date.now
},
status: {
type: Number
},
comments: [Comments],
tags: [Tags]
}));
I am a little new to this type of database, im used to MySQL on a LAMP stack.
Basically my question is as follows:
whats the best way to associate the Contents author to a User in the
DB?
Also, whats the best way to do the tags and categories?
In MYSQL we would have a tags table and a categories table and relate by keys, I am not sure the best and most optimal way of doing it in Mongo.
THANK YOU FOR YOUR TIME!!
Couple of ideas for Mongo:
The best way to associate a user is e-mail address - as an attribute of the content/comment document - e-mail is usually a reliable unique key. MongoDB doesn't have foreign keys or associated constraints. But that is fine.
If you have a registration policy, add user name, e-mail address and other details to the users collection. Then de-normalize the content document with the user name and e-mail. If, for any reason, the user changes the name, you will have to update all the associated contents/comments. But so long as the e-mail address is there in the documents, this should be easy.
Tags and categories are best modelled as two lists in the content document, IMHO.
You can also create two indices on these attributes, if required. Depends on the access patterns and the UI features you want to provide
You can also add a document which keeps a tag list and a categories list in the contents collection and use $addToSet to add new tags and categories to this document. Then, you can show a combo box with the current tags as a starting point.
As a final point, think through the ways you plan to access the data and then design documents, collections & indices accordingly
[Update 12/9/11] Was at MongoSv and Eliot (CTO 10gen) presented a pattern relevant to this question: Instead of one comment document per user (which could grow large) have a comment document per day for a use with _id = -YYYYMMDD or even one per month depending on the frequency of comments. This optimizes index creation/document growth vs document proliferation (in case of the design where there is one comment per user).
The best way to associate the Content Authors to a User in the MongoDB, is to take an array in Author Collection which keeps an reference to User. Basically Array because One Content/Book may have multiple Authors i.e. you need to associate one Content to many Users.
The best way for category is to create a different collection in your DB and similarly as above keep a array in Contents.
I hope it helps at-least a little.