I am new to MongoDB moving in from traditional SQL relational approach. I am working on a simple “Category has many Products” scenario (c#.Net). Where Category has
List<Product>
My questions are.
Question 1: On Add Product screen I have a drop down for Categories. So on Submit should I
First Insert Product in Products Collection and then
Push this Product in Nested Product of Categories collection.
_categoryCollection.Update(id, Update< Category>.Push…)
Question 2:
Or
We shouldn’t just have anything called “Product Collection”. Instead we should have only one Categories collection with Nested Products in it. And on submit just Push this new Product in respective Category.
Question 2.1 : What if we want to do this association for product with category after the product is added. ?
Or
Question 3:
Considering question one. Should we have CategoryId in Product entity ? does this makes any sense in No SQL concepts ?
I've always found this MongoDB article a good resource for such questions.
http://docs.mongodb.org/ecosystem/use-cases/product-catalog/
The questions you need to ask are, how will the data be accessed? What are my objects and how are they formed? Start with your programming first, create your classes (domain objects) and your access patterns, then worry about Mongo. You'll see, Mongo won't really get in your way. That is what is was meant to do.
So, going back to your scenario. If you know the categories are going to be big in number, need to be tightly controlled and manipulated often, then you could have a second collection for them and reference back to that collection's _id field in your category field in the product documents. Important is, the values themselves for the categories should be stored with each product document, in order to have fast reads due to one less query or the need to join the data.
Scott
A few considerations can be made here:
If a category has many products but a product cannot belong to more than one category, then
If number of products is not expected to be very large per category, then
Nest products inside category document
Else, use a different collection for products and use field 'categoryId' in them
Else, use use a different collection for products and use field 'categoryId' in them
Nest documents only when they have one definite parent and they are not huge or too many. Otherwise, the parent document will get huge with no way to control its size.
Related
I'm trying Google Cloud Datastore, but I have some doubts. I know that the ideal is to use a relational database for make a shop online, but I would like to try using Google Cloud Datastore.
How would a database of 2 tables be made? Stock and Products. The stock table has 2 columns (ref and units) and the product table has 3 columns (name, ref and price).
How would you do to get all the products that have stock?... like a join, I know that we do not have joins, that's why my doubt.
There has to be an efficient way to get the stock related to the products.
There are no tables in the Datastore, you have just entities with properties. And, depending on the client library you use, you might have entity models.
The Stock entities can have a Key property pointing to the corresponding Product entities. You query for the Stock entities, from the results you obtain the Product keys with which you pull the respective entities.
Or, if they're always in a 1:1 relationship I could use the exact same entity IDs for the corresponding Stock and Product entities, so I can make a Stock query and from the Stock entities in the result (or rather from their keys/IDs as I'd probably make keys_only queries) I can immediately compute the Product keys and get the respective entities (see re-using an entity's ID for other entities of different kinds - sane idea?).
But, in general, you might want to reconsider the general SQL approach of querying data to generate a report when you need it (and expecting that to be fast) and instead make the habit of performing the necessary computations ahead of time - whenever the data used in those computations changes. This is a much more scalable approach which works hand in hand with the datastore (and I guess with nosql in general). And for which you do not need to perform equivalent to SQL-style join ops. Basically raise the stock empty flag for a product right when you decrement its stock value, when you already know the product in question, so that you don't have to query for it later. While there also add it to the report (so that you'll have it ready when needed) and maybe trigger the restocking activity as well.
Consider a scenario of an application where I have users and projects and the requirement is users shall be assigned to projects. One user can be assigned to multiple projects. This is a many to many relationship. So what is the best way to model such a requirement.
I will like to discuss few approaches to model such a requirement :
- Embeded data model
In this approach I will embedd the user documents inside projects document.
Advantages : you get all the required data in one API call OR by fetching one single document.
Disadvantages : Data duplicacy which is OK
Real problem is if you update user information for eg user mobile no or name from users screen then this updated information should also be reflected under all embedded user documents. For this some bulk update query should be fired.
But is this the right way ???
- Embedding object references instead of objects (which is normalised)
In this case if we embedd user id's instead of user objects then the problem mentioned above wont be there but then we will have to make multiple network calls to get required data or make a seperate relation kond of document as we do in SQL.
Is this the best way ??
We have a same scenario, so i embed objectId. and for fill data for clients, populate users data in find function.
contract.find({}).populate('user').then(function(){});
There are few hard and fast rules, but usually with many-to-many relationships you would prefer references over embedding. This doesn't mean your data is totally flat/normalized.
For example, you could have a user document with an array of project ids. You could have the reverse for projects.
Think about your queries and how you will structure them. That can give you other hints about how to structure your documents.
Let's say I'm making a social app with MongoDB database, and I want users to be able befriend each other. Of course friendship is a mutual relation and user ids are integers. What would be the best approach?
Every user has a list of friend ids. Every time a bond is created/severed, both users' lists have to be updated.
Create join table 'friendship' containing IDs of 2 users. Every time bond is created I have to create two entries. 1->2 and 2->1
As no. 2, but always create only 1 bond with rule: lower_usr_id -> higher_usr_id. Assuming there are a lot of people and friendships. Wouldn't it save a lot of space and time?
It sounds like you're rather unclear about how MongoDB works. Joins aren't something that appears in MongoDB, and if you're trying to use MongoDB like a relational database you're doing it wrong.
I'm no expert on MongoDB, but I believe there are two common methods of modelling a one-to-many relationship:
Embedding one document inside another
Using references
Embedding a document inside another makes sense where the parent document in some sense "owns" the child document. For instance, in the context of a blogging application, a comment is owned by a post, so it might make sense to embed the comment inside the post.
For your use case, I don't believe that would be appropriate since the relationship is between objects of the same type. It would therefore make sense to record friendships as a reference to another object in the same collection.
Check out this link for further details.
I'm pretty new with NoSQL, MongoDB. How to deal with the many-to-many relation between 2 or multiple collections/documents? we'd better use DBRefs or embed? actually I've already read the MongoDB manual, but I didn't find something about many-to-many relation. I missed some points? or there is no this kind of relation in MongoDB? thx!
Embed versus reference
This is the problem of embedding versus referencing, and it’s a common source of confusion for new users of MongoDB. There’s a simple rule of thumb that works for most schema design scenarios: Embed when the child objects always appear in the context of their parent. Otherwise, store the child objects in a separate collection.
Embed or reference it depends on the application. Suppose you’re building a simple application in MongoDB that stores blog posts and comments.If the comments always appear within a blog post, and if they don’t need to be ordered in arbitrary ways (by post date, comment rank, and so on), then embedding is fine. But if, say, you want to be able to display the most recent comments, regardless of which post they appear on, then you’ll want to reference. Embedding may provide a slight performance advantage, but referencing is far more flexible.
Many-to-many
In RDBMSs, you use a join table to represent many-to-many relationships; in MongoDB, you use array keys. For example each product contains an array of category IDs, and both products and categories get their own collections. If you have two simple category documents
{ _id: ObjectId("4d6574baa6b804ea563c132a"),
title: "Epiphytes"
}
{ _id: ObjectId("4d6574baa6b804ea563c459d"),
title: "Greenhouse flowers"
}
then a product belonging to both categories will look like this:
{ _id: ObjectId("4d6574baa6b804ea563ca982"),
name: "Dragon Orchid",
category_ids: [ ObjectId("4d6574baa6b804ea563c132a"),
ObjectId("4d6574baa6b804ea563c459d") ]
}
I have two tables/collections; Users and Groups. A user can be a member of any number of groups and a user can also be an owner of any number of groups. In a relational database I'd probably have a third table called UserGroups with a UserID column, a GroupID column and an IsOwner column.
I'm using MongoDB and I'm sure there is a different approach for this kind of relationship in a document database. Should I embed the list of groups and groups-as-owner inside the Users table as two arrays of ObjectIDs? Should I also store the list of members and owners in the Groups table as two arrays, effectively mirroring the relationship causing a duplication of relationship information?
Or is a bridging UserGroups table a legitimate concept in document databases for many to many relationships?
Thanks
What I've seen done, and what I currently use are embedded arrays with node id's in each document.
So document user1 has property groups: [id1,id2]
And document group1 has property users: [user1]. Document group2 also has property users: [user1].
This way you get a Group object and easily select all related users, and the same for the User.
This takes a bit more work when creating and updating the object. When you say 2 objects are related, you have to update both objects.
There's also a concept DBReferences in MongoDB and depending on your driver, it'll pull referenced objects automatically when retrieving a document.
http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef
In-case anyone interested, I just bumped into a very good article posted in mongoDB blog. 6 Rules of Thumb for MongoDB Schema Design. There are 3 parts in this article, after reading all 3 you'll have a good understanding.
Let's understand Many to Many Relations with an examples
books to authors
students to teachers
The books to authors is a few to few relationship, so we can have either an array of books or authors inside another's document. Same goes for students to teachers. We could also embed at the risk of duplication. However this will required that each student has a teacher in the system before insertion and vice versa. The application logic may always not allow it. In other words, the parent object must exist for the child object to exist.
But when you have many to many relationship, use two collections and have a true linking.