How to construct this database in mongodb? - node.js

say i have two collections in mongodb,one for users which contains users basic info,and one for apps which contains applications.now if users are allowed to add apps,and the next time when they login, the web should get the user added app for them.how should i construct this kind of database in mongodb.
users:{_id:ObjectId(),username:'username',password:'password'}
apps:{_id:ObjectId(),appname:'',developer:,description:};
and how should i get the user added app for them??? should i add something like addedAppId like:
users:{_id:ObjectId(),username:'username',password:'password',addedApppId:[]}
to indicate which app they have added,and then get the apps using addedAppId???

Yep, there's nothing wrong with the users collection keeping track of which apps a user has added like you've indicated.
This is known as linking in MongoDB. In a relational system you'd probably create a separate table, added_apps, which had a user ID, app ID and any other relevant information. But since you can't join, keeping this information in the users collection is entirely appropriate.
From the docs:
A key question when designing a MongoDB schema is when to embed and when to link. Embedding is the nesting of objects and arrays inside a BSON document. Links are references between documents.
There are no joins in MongoDB – distributed joins would be difficult on a 1,000 server cluster. Embedding is a bit like "prejoined" data. Operations within a document are easy for the server to handle; these operations can be fairly rich. Links in contrast must be processed client-side by the application; the application does this by issuing a follow-up query.
(this is the extra bit you'd need to do, fetch app information from the user's stored AppId.)
Generally, for "contains" relationships between entities, embedding should be be chosen. Use linking when not using linking would result in duplication of data.
...
Many to many relationships are generally done by linking.

Related

Node Express APP 1 to N (with MongoDB)

we are developing a big node app with express and MongoDB. We are trying to get the best performance, because we will have multiple clients (maybe 100+) running on the same server.
We were thinking in a one-to-n APP, one instance, one database and multiple clients accessing their domains.
I want to know what is the best settings for this scenario (one server, multiple clients) to performance and development
One instance, one database (clients data would be identified by a company ObjectId on the entry and clients would access a domain or subroute)
One instance, multiple tables (or databases, what is the best?)
Multiple instances, multiple tables
Any other ideas?
On the first setting, the developers will always worry about the current company and this can bring limitations to the app
On the second setting, the concern will continue but the company will not interfere on the database entries (more clean model)
On the third setting (maybe the best for development) only one company will be treated and brings a lot of possibilities, but may bring performance issues (all instances will run on a single server)
Other settings I have not thought of can be better.
Notes:
We are using the mongoose library
I have some experience with WordPress and i like the way themes and plugins are created for it. We are trying to achieve a level of performance similar to Wordpress with PHP (several Wordpress running on a server efficiently)
sorry about bad english
You don't need to manage multiple instance as you can create a company collection and in that collection you can store every single company and then you just need to create a reference of all these values in users.Please make sure that you have made unique index on company collection.It is really easy handle such scenarios in RDBMS(mysql).
And one more thing you can also run multiple mongod client on same instance by just changing the port and if you are looking for that sort of solution then you can do that as well.
Please note following things before using mongo:-
Please use mongo only if you have over TB's of data because that doesn't make any sense to use mongodb for some mb's or gb's of data.
Use of indexes is must in mongo if you want maximum performance.
Mongo stores all the indexes in main memory and if the indexes size is more then memory that it start swapping of indexes which is really costly and hence please make sure that you have different servers for your application and your db.
I still says it would be better to use RDBMS if you don't have TB's of data to deal with.
Why this approach:-
Let me give you a scenario.
You have 100 companies and with in 100 companies you have 1000 users for each of the company. i.e. you have 1L records in your user collection.Now i want to delete a single user or i want to update a user or i want to fetch a user from a single company then i don't need to traverse my complete database as i can make a index on my user collection using user-id and company id(compound index) or even i can make a simple filter query on company id.
For index please read this
https://docs.mongodb.com/manual/core/index-compound/
And btw we are not saving company id as an object instead i am saving only the value of _id from company collection.

CouchDB simple document design: need feedback

I am in the process of designing document storage for CouchDB and would really appreciate some feedback. These documents are to represent "assets".
These databases will also be synced locally to the browser via pouchdb.
Requirements:
Each user can have many assets
Users can share assets with others by providing them with a URI such as (xyz.com/some_id). Once users click this URI, they are considered to have been "joined" and are now part of a group.
Group users can share assets of their own with other members of the group.
My design
Each user will have his/her own database to store assets - let's call it "user". Each user DB will be prefixed with the his/her unique ID.
Shared assets will be stored in a separate database - let's call it "group". shared assets are DUPLICATED here and have an additional field for userId (to indicate creator).
Group database is prefixed with a unique ID just like a user database is prefixed with one too.
The reason for storing group assets in a separate database is because when pouchdb runs locally, it only knows about the current user and his/her shared assets. It does not know about other users and will should not query these "other" users' databases.
Any input would be GREATLY appreciated.
Seems like a great design. Another alternative would be to just have one database per group ("role"), and then replicate from a user's group(s) into their local PouchDB.
That might get hairy, though, when it comes time to replicate back to the server, because you're going to have to filter the documents as they leave the user's local database, depending on which group-database they belong to. Still, you're going to have to do that on the server side anyway with your current design.
Either way is fine, honestly. The only downside of your current approach is that documents are duplicated on the server side (once per user-db and once per group-db). On the other hand, your client code becomes dead-simple, because you don't have to do any filtered replication. If you have enough space on your server not to worry about it, then I would definitely go with your approach. :)

how to generate a unique id in node.js for users registering a webservice?

I am building a webservice with node.js and I am registering users in my service. I am using node.js + mongodb for my db and once I create a new user I also want to create a unique id for them and send that back as a response, just like all the great services like fb that send u back the facebook id. I do not want to send back the _id from mongodb, so how do I generate a unique id for every user in node, also is it better to do it this way or just send back the mongo _id.
is it better to do it this way or just send back the mongo _id
If you have to ask, it is better to just send back the mongo _id. Unless you have iron-clad reasoning behind why that simple, straightforward, make-life-easy-for-everyone technique is problematic, by all means, just send back the mongo _id.
If you decide the mongo _id is not good enough for you (probably due to FUD as opposed to any realistic reasoning), you have the following extra challenges you are adopting without any benefit:
you have to think more carefully about your indexes
Helper libraries functions like findById don't work for you anymore
Now you have 2 huge, hard-to-eyeball IDs to deal with on every record
helper libraries like mongoose are also going to be challenging to leverage
You will have to be mapping back and forth between _id and mySuperAwesomeExtraneousId constantly during debugging for the entire lifetime of your app
K.I.S.S.
That said, you can always just use an additional mongo ObjectId as they are perfectly valid unique Ids:
const mongo = require('mongodb')
let mySuperAwesomeExtraneousId = new mongo.ObjectID()
Use coupon-code.This is simple to use and solves most of the use cases for generation of unique ids.
https://github.com/appsattic/node-coupon-code
https://github.com/broofa/node-uuid
There are numerous good reasons for not sending back the _id created by Mongoose by default for example. For one, those IDs could easily be guessed by a rogue entity or hacker. And it's also never a good idea to expose your database ids anyway.
For an app that relies solely on a unique ID for a password-less account access, generating a highly unique hash id may be the best option. The perfect node module for that is hashids
You may also give crypto a try:
require('crypto').randomBytes(48, function(ex, buf) {
var token = buf.toString('hex');
});
good luck!
Use http://mongoosejs.com as an abstraction layer to MongoDB. It will ensure that you always have the _id available. It also will manage many other things, such as validation, connections, etc.
Pros: It is simpler to use than raw drivers, while at the same time maintaining all the power of a raw MongoDB driver. You will be up and running in about 20 minutes after visiting the mongoose website. Its one of the few times you don't trade off power for simplicity. It is a thin abstraction layer, you will have a net performance gain in code by having this single, robust layer in place then by trying to re-invent the wheel on every single part of your code that needs to access the DB. It supports every single MongoDB feature. It provides validation. It provides a simple interface to managing indexes. It automatically creates databases and collections. Built by the same guys that made ExpressJS, Socket.IO and Mocha for node.js. The list goes on.
Cons: Does not support multiple MongoDB connections. This is usually not a problem though because you will most likely use MongoDB's sharding features before you need to create multiple connections to multiple MongoDB clusters. It has a silly name.
We have been using Mongoose in production environments for quite sometime. If you want to see it in action, look at ZingProject.com. Its entirely node.js + mongoose over MongoDB. Its lightning fast.

ACL best practices, store roles in user object, or separate table/collection?

I am using nodejs, and have been researching acl/authorization for the past week. I have found only a couple, but none seem to have all the features I require. The closest has been https://github.com/OptimalBits/node_acl, but I don't think it supports protecting resources by id (for example, if I wanted to allow user 12345 and only user 12345 to access user/12345/edit). Hence, I think I will have to make a custom acl solution for myself.
My question regarding this is, what are some pros and cons to storing roles (user, admin, moderator, etc.) under each user object, as opposed to creating another collection/table that maps each user with their authorization rules? node_acl uses a separate collection, whereas most of the other ones depend on the roles array in user objects.
By the way, I am using Mongodb at the moment. However I have not researched the pros and cons yet of using relational vs. nonrelational databases for authentication yet, so if let me know if your answer depends on that.
As I was typing this up, I thought of one thing. If I store roles in a separate collection, it is more portable. I would be able to swap out the acl system much more easily. (I think?)
The question here seems like it could be abstracted from "where should I store my roles" to "how should I store related information in Mongo (or NoSQL in general)". It's a relation vs non-relational modeling issue.
Non-Relational
Using Node + Mongo, storing the roles on the user will make it really easy to determine if a user has access to the feature, given that you can just look in the 'roles' property. The trade off is that you have lots of duplicate information ('user_read' could be a role on every user account) and if you end up changing that property, you'll need to update it inside every user object.
You could store the roles in their own collection and then store the id for that entry in the Roles collection on your User model, but then you'll still need to fetch the actual record from the collection to display any of it's information (though arguably this could be a rare occurrence)
Relational
Storing these in a relational DB would be a more "traditional" approach in that you can establish the relationships between the tables (via FKs / join tables or what not). This can be a good solution, but then you no longer have the benefits of using a NoSQL database.
Summary
If the rest of your app is stored in Mongo and has to stay there (for performance or whatever constraint) then you are probably better off doing it all in Mongo. Most of the advice I've come across says don't mix & match data stores, e.g. use one or the other, but not both. That being said, I've done projects with both and it can get messy but sometimes the pros outweigh the cons.
I like #DavidWelch answer, but I'd like to tackle the question from another perspective because the library mentioned gives the option to use a different data store entirely.
Storing roles in a separate data store:
(Pro) Can make the system more performant if you are using a faster data store. (More advantageous in distributed environments?)
(Con) You will have to ensure consistency between the two data stores.
General notes:
You can add roles/permissions such as 'blog\123' in acl. You can also give a user permissions based on verbs such as put, delete, get, etc..
I think it is easier to create a pluggable solution that does not depend on your storage implementation. Perhaps that is why acl does not store roles in the same collections you have.
If you choose to keep the roles in your own collection, consider adding them to a token (JWT). That way, you will not have to check your collection for every request that needs authorization.
I hope that helped.

Express.js and Mongoose model relationships - in model or router?

Building a REST API with Express.js and Mongoose on node - I have stumbled upon a code design issue - where should I handle relationships - in models or routers?
First, I am pretty new to the MVC and such, and even though express.js is not a full MVC, I would like to follow best design practices.
The issue is rather easy - the app has users, each user can have multiple documents (projects, orders, etc). Obviously I have to at least store the user ID for every document that is created. The question is - where should I do that?
I can get the user ID from the session in each router and attach it to a document, or I can just set the current user ID to a global variable, for example app.currentUserID and use that in my model to attach the ID to the document.
There are actually more interesting cases, where a user can have multiple organizations, and I have to set the organization ID for each document that the user creates when operating with a specific organization.
So the question is: should I handle this kind of logic in my router (express does not have 'controllers' as such) or model?
Do it in the model. Even if you're not creating an enforced relation, storing the actual ID of a related object still changes the model, so there's no reason to leave the logic in the router.
MongoDB (and Mongoose) doesn't have referential integrity like relational databases do. This means that the database will not give you an error if you insert a relation to an object which doesn't exist. It lets the application code handle those relations.
Mongoose is an attempt to bring structure to an otherwise pretty liberal nosql DB. As such, it offers an ability to create such relations with the ObjectId schema type.
Read the following SO answer for more info: https://stackoverflow.com/a/7813331/1801

Resources