Restrict document fields addition in MongoDB? - mongodb

Does MongoDB provide any mechanism to restrict addition of a new field to a document in a collection?
I would think that the best way to do that would be using some kind of "add new field" privilege, but it seems that MongoDB has got just two roles - readonly and normal. Is there any other way to "lock" a collection?

Related

MongoDb constraint allowing only one entry in collection

Can I make a constraint to prevent more than one document appearing in a collection? The collection will store the version of the database structures
In SQL I would have put a check constraint on the table that checks the count of rows in the table is less than 2
I believe the best way would be using User-Defined Roles to provide Collection-Level Access Control. You can create a document with an innitial database_version and posteriorly assign to your user a role that restricts the access to the collection to only find and update documents.
P.S.:While searching for a solution you may have come across a possible alternative called Capped Collections. It won't work in your case as Capped Collections restrict updates if the updates result in increased document size.

Collection with single entity restriction

I would like to create collection where only one entity should be stored.
Questions:
Is it possible to create restrictions for this collection on db level?
What are the best practices for CRUD application dealing with such collection?
You can use schema validation to be sure that new documents will respect your schema. This feature appears in 3.2, but was modified since 3.6 with use of JSON schema. Check the right doc version.

Create MongoDB Dynamic view

I'm new in MongoDB, and i would like to know if there is a way to create a dynamic view inside MongoDB.
Let me be more precise :
In mongo i have a collection with financial datas, and an GUI interface wich display the datas.
But each users could reduce the datas by adding or removing columns to the grid, and filter the grid : a classic usecase.
What i would like to do, is to create a collection for each user that listen to the master table, according to the users filters: something like this :
mongo.createView(masterCollection, filters, mapReduce)
In this scenario, mongo update each view, each time a modification is done in the master collection (update, delete, insert).
I could do something like this manualy : create a table for a user, and use a tailable cursor on my master collection with the user filters and mapReduce, and the add, remove, or update the document in the user collection.
But, i have up to 100 simultaneous users, and it would open and keep alive 100 tailable cursors on the primary collection. I don't know enough mongo, but i think it's not a best practice to do something like this.
Actualy i have a thread for each user that get data for the collection, according to the user filters, every 5 secondes.
Could you please let me now if there is a native mongo way to handle this scenario or a way to create a user view in mongo.
Thank you
Starting with MongoDB v3.4 (community and enterprise edition), there is a support for creating read only views from existing collections or other views. This feature utilises MongoDB aggregation pipeline.
To create a view from the mongo shell, you could do:
db.createView(<view>, <source>, <pipeline>, <collation> )
Using your scenario above, you could create:
db.createView(<"user_view_name">, <"source_collection_name">, <"aggregation pipeline operators">)
See all the available Aggregation Pipeline Operators - i.e. not only you could filter, you could also modify the document structure.
See MongoDB Views behaviour for more information.
MongoDB Enterprise has a feature called 'Single View' which implements database views. It's more for aggregating data from multiple tables (e.g. parent/child relationships), and may be more than what you're looking for but is worth checking out. The downside, it's only available in the pricey Enterprise edition.
Check out the description here

Restrictions on drop collections on mongodb

Is there a way to add a restriction when deleting collections that are referenced by id in other collections using mongodb or mongoose?
I need something like "on delete restrict" from sql to use on mongodb.
References from one collection to another are not explicit. So Mongo has no way to know that an ObjectId property in a document refers to the id of another document, nor in which collection. So I believe it's not possible to have such restrictions.
MongoDB doesn't support this feature, you can implement in your own application.
Keep a refcount field in your document to track referenced count.
db.coll.remove({refcount: 0})

How to manage relation in MongoDB?

I am new to MongoDB.I have one Master Collection user_group.The sample document is shown bellow.
{group_name:"xyz","previlege":["Add","Delete"],...}
And second collection user_detail
{"user_name":"pt123","group_name":"xyz",...}
How can I maintain relation between these two collections.Should I use reference from user_group into user_detail or any other alternative?
Often, in MongoDB, the "has many" relationship is managed on the opposite side as in a relational database. A MongoDB document often will have an array of ObjectIds or group names (or whatever you're using to identify the foreign document). This is opposed to a relational database where the other side usually has a "belongs to" column.
Do be clear, this is not required. In your example, you could store an array of user details IDs in your group document if it was the most common query that you were going to make. Basically, the question you should ask is "what query am I likely to need?" and design your documents to support it.
Simple answer: You don't.
The entire design philosophy changes when you start looking at MongoDB. If I were you, I would maintain the previlege field inside the user_detail documents itself.
{"user_name":"abc","group_name":"xyz","previlege" : ["add","delete"]}
This may not be ideal if you keep changing group priviledges though. But the idea is, you make design your data storage in a way so that all the information for one "record" can be stored in one object.
MongoDB being NoSQL does not have explicit joins. Workarounds are possible, but not recommended(read MapReduce).
Your best bet is to retrieve both the documents from the mongo collections on the client side and apply user specific privileges. Make sure you have index on the group_name in the user_group collection.
Or better still store the permissions[read, del, etc] for the user in the same document after applying the join at the client side. But then, you cannot update the collection externally since this might break invariants. Everytime an update to the user group occurs, you will need to apply those permissions(privileges) yourself at the client side and save those privileges in the same document. Writes might suffer but reads will be fast(assuming a few fields are indexed, like username).