MongoDB, how to manage user related records - node.js

I'm currently trying to learn Node.js and Mongoodb by building the server side of a web application which should manage insurance documents for the insurance agent.
So let's say i'm the user, I sign in, then I start to add my customers and their insurances.
So I have 2 collection related, Customers and Insurances.
I have one more collection to store the users login data, let's call it Users.
I don't want the new users to see and modify the customers and the insurances of other users.
How can I "divide" every user related record, so that each user can work only with his data?
I figured out I can actually add to every record, the _id of the one user who created the record.
For example I login as myself, I got my Id "001", I could add one field with this value in every customer and insurance.
In that way I could filter every query with this code.
Would it be a good idea? In my opinion this filtering is a waste of processing power for mongoDB.
If someone has any idea of a solution, or even a link to an article about it, it would be helpful.
Thank you.

This is more a general permissions problem than just a MongoDB question. Also, without knowing more about your schemas it's hard to give specific advice.
However, here are some approaches:
1) Embed sub-documents
Since MongoDB is a document store allowing you to store arbitrary JSON-like objects, you could simply store the customers and licenses wholly inside each user object. That way querying for a user would return their customers and licenses as well.
2) Denormalise
Common practice for NoSQL databases is to denormalise related data (ie. duplicate the data). This might include embedding a sub-document that is a partial representation of your customers/licenses/whatever inside your user document. This has the similar benefit to the above solution in that it eliminates additional queries for sub-documents. It also has the same drawbacks of requiring more care to be taken for preserving data integrity.
3) Reference with foreign key
This is a more traditionally relational approach, and is basically what you're suggesting in your question. Depending on whether you want the reference to be bi-directional (both documents reference each other) or uni-directional (one document references the other) you can either store the user's ID as a foreign user_id field, or store an array of customer_ids and insurance_ids in the user document. In relational parlance this is sometimes described to as "has many" or "belongs to" (the user has many customers, the customer belongs to a user).

Related

MongoDB standards for User/Room relations

So I have this MEAN-project I hobby on in my spare time.
Right now I'm setting up users and rooms, and am a bit hesitant about progressing further, as I am unsure about the proper protocol of db's in general.
As I recall, you're not supposed to have a Many-To-Many relationship; rather, you're supposed to have a relation table.
Right now, my User schema has an array of rooms he is in, and my Room schema has an array of users tied to it (the third and last schema being Message).
Is it better to have a userroomrelation doc that holds a PK, an id of one room, and then a list of all users in this room?
Thanks,
Rasmus
MongoDB isn't a relational database like *SQL databases (hence why MongoDB is called NoSQL), so using a relation table is fairly inefficient in Mongo. Holding an array of user _id's in the room collection is about as ideal as you could get, if you don't want repeat data.
Here are some more indepth answers on many-to-many in MongoDB.
How can a User be in more than one room? Isn't that just a property on the User? And if you index that why would you also need to store it on the Room?
There is no one right way, it really depends on how many of each object you have and if it's a small number (as rooms and users implies) you may be better with a simpler and more robust (cannot store impossible values) approach like having a single property on a user RoomId. That's never going to be inconsistent and if you need to find the set of users in a given room it's a cheap query.
In MongoDB you CAN denormalize the data and store an array on each object containing part or all of the other object, but you can also create an effective join collection if you want to.
For example you could have a collection {UserId, RoomId, DateTimeEntered, DateTimeLeft} with appropriate indexes which allows you to quickly find all the users in a given room at a given time. Once you have the set of Ids you could go load them if you need them for display OR you could add the fields you need for display to this table {UserId, UserName, ...} BUT then you have the problem of maintaining that data if it ever changes OR keeping it intact if you need to know that when they entered the room that's what it was called.
There are also a TON of other questions on StackOverflow relating to how you should store related data, I suggest you go read those also.

How to selectively replicate private and shared portions of a CouchDB database?

We're looking into using CouchDB/CouchCocoa to replicate data to our mobile app.
Our system has a large number of users. Part of the database is private to each user -- for example their tasks. These I've been able to replicate without problem using filtered replication.
Here's the catch... The database also includes shared information only some of which pertains to a given user. How do I selectively replicate that shared information? For example a user's task might reference specific shared documents. Is there a way to make sure those documents are included in the replication without including all the shared documents?
From the documentation it seems that adding doc_ids to the replication (or adding another replication with those doc ids) might be one solution. Has any one tried this? Are there other solutions?
EDIT: Given the number of users it seems impractical to tag each shared document with all the users sharing it but perhaps that's the only way to do this?
Final solution mostly depends on your documents structure, but currently I see two use-cases:
As you keep everything within single database, probably you have some fields set to recognize, that document is shared or document is private, right? Example:
owner: "Mike"
participants: [] // if there is nobody mentioned, document looks like as private(?)
So you just need some filter that would handle only private documents and only shared ones: by tags, number of participants, references or somehow.
Also, if you need to replicate some documents only for specific user (e.g. only for Mike), than you need special view to handle all these documents and, yes, use replication by document ids, but this wouldn't be an atomic request: you need some service script to handle these steps. If shared documents are defined by references to them, than the only solution is the same: some service script, view that generated document reference tree and replication by doc._id's.
Review your architecture. Having per user database is normal use-case for CouchDB and follows way of data partitioning and isolation. So you may create per user database that would be private only for that user. For shared documents you may create additional databases playing with database members of security options. Each "shared" database will handle only certain number of participants by names or by groups, so there couldn't be any data leaks unless that was not a CouchDB bug(:
This approach looks too weird from first sight, but everything you've needed there is to create some management script that would handle database creation and publication, replications would be easy as possible and users data is in safe.
P.S. I've supposed that "sharing" operation makes document visible not for every one, but for some set of users. If I was wrong and "shared" state means "public" state than p2. will be more simpler: N users databases + 1 public one.

Storing information in a forum like web site

Suppose that we have a web site where each person has a profile and other people write comments to the persons profile. (like the wall in facebook). What is the best way to store the comments made for a person ? I was thinking like a relational database type of thing where there will be a field to hold all the comments for a person in the form of a long string separated with some kind of delimiter but I am not sure if this is the best way. Any ideas ?
You'll have two separate tables one for Users one for Comments, all the entries having their unique IDs, schema would go like:
Users (ID, name, mail, etc)
Comments (ID, for, from, time, content, etc)
Where for and from fields are User IDs.
postgresql, mysql, sqlite or even leveldb if you want simple key value store. There's a lot of tutorials out there to get started with any of them.
The problem with Relational databases is that they do not scale well to super massive social networking sites. When your table starts to get huge the queries will start to take more and more time. If your site is going to be pretty small then a relational database is fine. I think that you may want to investigate "NoSql" databases.
Start here:
http://nosql-database.org/

Understanding Kohana ORM Relationships

I know this question has been asked a million times, but I can't seem to find one that really gives me a good understanding of how relationships work in Kohana's ORM Module.
I have a database with 5 tables:
approved_submissions
-submission_id
-contents
favorites
-user_id
-submission_id
ratings
-user_id
-submission_id
-rating
users
-user_id
votes
-user_id
-submission_id
-vote
Right now, favorites,ratings, and votes have a Primary Key that consists of every column in the table, so as to prevent a user favoriting the same submission_id multiple times, a user voting on the same submission_id multiple times etc. I also believe these fields are set up using foreign keys that reference approved_submissions and users so as to prevent invalid data existing in the respective fields.
Using the DB module, I can access and update these tables no problem. I really feel as though ORM may offer a more powerful and accessible way to accomplish the same things using less code.
Can you demonstrate how I might update a user voting on a submission_id? A user removing a favorite submission_id? A user changing their rating on a particular submission_id?
Also, do I need to make changes to my database structure or is it okay the way it is?
You're probably looking for has_many_through relationships.
So to add a new submission, you'd do something like
$user->add('submissions', $submission);
and to remove
$user->remove('submissions', $submission);
You may want to consider restructuring your database table and key names so you don't end up doing a lot of configuration.

Associating documents in Lotus notes

When a document is associated with another document (e.g. as address connected to a customer), how does notes stores the information? Does it create a new document to represent the association or does it tags the linked document as a response document?
I'm guessing you're asking because you are reviewing someone else's database, but in case you're starting from scratch and want to know the best approach I'll answer that too.
The short answer:
Notes isn't relational. I'd bet the address is stored in the same document as the customer.
The long answer:
If there are separate customer and address documents, there are usually some loose connections between the documents, perhaps based on a UniqueID field or perhaps just a name. For instance, the customer form might look up to an address view and pick that address based on the customer's name, meaning the address documents have the customer's name stored on them.
Sometimes a link can be created via the parent/child relationship of documents and responses, but that's more often used in discussion thread databases or very special cases.
Ultimately it's up to the developer of the Notes application to decide how to link the data. My suggestion, especially if you come from a relational db background, is to use the #UniqueID formula in a hidden text field that is computed on compose. That will stamp a GUID on your document and you can use that for referencing the document like you would a foreign key to a table. That helps to keep data somewhat normalized.
There is no automatic way that Notes associates one document with another, except for response documents, which when created get set with a $REF item that include the GUID of the parent document. Again, this isn't an ideal way to relate documents like customers and addresses because the relationship can't be leverage to make development easier. The document/response hierarchy is mostly just useful for organizing documents within a view.

Resources