Best document model to store students and completed trainings in MongoDB - mongodb

I have two models named Students, Trainings. I want to store student's completed trainings.
Currently my Student model is like below:
{
"_id": "abcd"
"name": "Student 1"
"completedTrainings": ["asds", "asdasd"]
}
When I list completed trainings, I'm getting all trainings with $in.
Is it right way to my use case, are there better alternatives ?

Related

Mongoose model data deeper than 1 level

I'm trying to design my schema in Mongoose which contains the following collections:
Customers
Expenses
Categories
Instead of embedding the expenses within the customer, I have decided to create its own collection as a customer could potentially have thousands of expenses.
My first question is, is that the best way to model this? i.e. In the expenses collection, would it be best to have a single document for each expense that has a reference to the customer it belongs to?
My second question is about modeling the expenses.
I want to have something like this (oversimplified it here):
{
"_id": Object,
"customer_ref": Object,
"details": {
"amount": 20.00,
"description": "An expense"
},
"date_created": "April 5th..."
}
I have been able to create schema models where the data is one level deep but I'm not sure how you achieve something like the above where I have nested data.
Is mongoose designed to only deal with one level deep data, so I should avoid nesting altogether?
If not how do I achieve something like the above?

MongoDB design speculation

I am digging the MongoDB related questions/answers but one thing is still not obvious.
Let's consider the following Product collection:
{
"manufacturer": "Man1",
"model": "Model1"
}
Let's say we have 1.000.000 products, and I would like to create
a dropdown of manufacturers (which would be max 50 options).
In this case every time I have to use the .distinct() function on that huge product collection.
Is this the right way to do it ?
I am a bit concerned about the performance.
Or should I create a separate collection for manufacturers and keep it synced ?
UPDATE
Thanks for all the answers, I still considering them.
And what if I do the following:
Manufacturer:
{
"name": "Man1",
"models": [
{
"name": "Model1",
"products": [Product1, Product2]
}
],
}
and Product
{
"manufcturer": "Man1",
"model": "Model1"
"manufacturer_id": Manufacturer1,
"model_id", Model1
}
First. If you've large number of records, you'd never want to load all the data in just one request to populate the list, dropdown or whatever it is. Rather, implementing something like load more options suits more. Just like pagination.
And you can manage to get like 20,40 records per request and do any optimization on those small chunk of data.
You can create a separate collection for manufacturers. You just have to keep it in sync, after every addition/update/deletion of product from products collection.
I think you can think of designing your Product collections like this:
{
"manufacturer": "Man1",
"model": "Model1"
"Product" :[Product1,Product2]
}
And having an index on "manufacturer" will optimize your query to get list of manufacturers

MongoDB collections design

I've got such four tables:
Point is that users that joined in particular group have access to a survey for time interval from date to date. How should i organize collection structure of such db in mongodb?
For survey and questions this will be a simple colection of surveys with an array of questions. But for this behavior with start/end of survey it is not clear for me how to store this data.
What about something like.
Groups
{
_id : "group1",
"members" : [{"name":"A"...},{"name":"B"...}],
"surveys" : [{"surveyId":"survey1", "startDate": ISODate(),"endDate":ISODate()},{"surveyId":"survey2", "startDate": ISODate(),"endDate":ISODate()}]
}
Surveys
{
_id : "survey1",
questions : [{"text":"Atheist??"...},{....}]
}
Honestly, it depends on what pattern you want to use, I mean you can embed groups inside survey also with registration details.

Designing mongo 'schema' for RESTful application

I'm trying to teach myself mongo through writing an application, and I'm struggling with the best way to design the mongo 'schema' (I know it's schemaless, but that is probably the core issue with my understanding in that I'm coming from a relational background)
Anyway, the application is a Gift List manager, where a user can create a Gift List and can add Gifts they would like to receive to their list. Other users can subscribe to the list, and can mark a Gift from the Gift List as claimed/purchased. (So as to prevent the problem of getting duplicate gifts at Christmas!)
At the moment my GiftLists collection is not 'relational' and is simply a collection of GiftList documents with sub documents for the Gifts, like this:
{
"GiftLists": [
{
"_id": {
"$oid": "55e9924848c4ffd723890b48"
},
"description": "Xmas List for Some User",
"gifts": [{
"description": "Mongo book"
"claimed": false
},
{
"description": "New socks"
"claimed": false
},
{
"description": "New socks"
"claimed": false
}],
"owner": "some.user",
"subscribers": ["some.other.user", "my.friend"]
}
]
}
The idea is that some.user is the owner of the Gift List and has added 3 items he would like to receive. some.other.user has subscribed to the list and can see the Gift List and it's Gifts. He may choose to buy one of the gifts, so needs to mark it as claimed so that my.friend does not also buy it.
At the moment, each Gift in the gifts array is a sub-document without its own id, and I think this is where I'm getting stuck in my understanding/thinking.
I'm trying to provide the app functionality with a RESTful interface.
To POST a new Gift List the url is /giftList/add where the request body is the new Gift List
To GET an individual Gift List including the child Gift's the url is /giftList/<listId> - eg: /giftList/55e9924848c4ffd723890b48
With the above in mind, my natural next step is to be able to mark a Gift as claimed, perhaps with:
PUT to the url /gift/claim/<giftId>
But I don't have any ids on the Gift sub documents
So maybe my url should be:
/giftList/<listId>/claim/<giftId>
But again, I don't have an id on the Gift sub document
Or maybe I try to use the description of the item
/gift/claim/<gift description> eg: /gift/claim/Mongo+book
But what if more than one person had a Gift List containing 'Mongo book', and URL encoding the characters of the description could be messy
Or maybe I reference the Gift List
/giftList/<listId>/claim/<gift description> eg: /giftList/55e9924848c4ffd723890b48/claim/New+socks
But which instance of 'New socks' am I claiming? (after all, everyone needs lots of new socks for Christmas!)
Or maybe I reference the index of the Gift
/giftList/<listId>/claim/<gift index> eg: /giftList/55e9924848c4ffd723890b48/claim/2
But this feels fragile (as it implies that the list must always be presented in the same sequence)
To me what it really feels like is that I need another collection, just for the Gifts, where each Gift document has its own id, which I can then reference in my RESTful url. And either the Gift has a reference to it's parent GiftList, or the GiftList has an array of references to the Gifts
But this is all a very 'relational' way of thinking ... isn't it ?
What's the best way of doing this? Or, if there is no 'best' way, what are my options?
You could solve this with a new collection, or you could add an unique identifier field to each list entry. The MongoDB solution for unique identifiers is generating an ObjectId, just like those used for the _id field of documents. Most MongoDB database drivers should expose functionality for generating ObjectId's. For details, consult the documentation of your database driver.

How to design product category and products models in mongodb?

I am new to mongo db database design,
I am currently designing a restaurant products system, and my design is similar to a simple eCommerce database design where each productcategory has products so in a relational database system this will be a one (productcategory) to many products.
I have done some research I do understand that in document databses.
Denationalization is acceptable and it results in faster database reads.
therefore in a nosql document based database I could design my models this way
//product
{
name:'xxxx',
price:xxxxx,
productcategory:
{
productcategoryName:'xxxxx'
}
}
my question is this, instead of embedding the category inside of each product, why dont we embed the products inside productcategory, then we can have all the products once we query the category, resulting in this model.
//ProductCategory
{
name:'categoryName',
//array or products
products:[
{
name:'xxxx',
price:xxxxx
},
{
name:'xxxx',
price:xxxxx
}
]
}
I have researched on this issue on this page http://www.slideshare.net/VishwasBhagath/product-catalog-using-mongodb and here http://www.stackoverflow.com/questions/20090643/product-category-management-in-mongodb-and-mysql both examples I have found use the first model I described (i.e they embed the productCategory inside product rather than embed array of products inside productCategory), I do not understand why, please explain. thanks
For the DB design, you have to consider the cardinality (one-to-few, one-to-many & one-to-gazillions) and also your data access patterns (your frequent queries, updates) while designing your DB schema to make sure that you get optimum performance for your operations.
From your scenario, it looks like each Product has a category, however it also looks like you need to query to find out Products for each category.
So, in this case, you could do with something like :
Product = { _id = "productId1", name : "SomeProduct", price : "10", category : ObjectId("111") }
ProductCategory = { _id = ObjectId("111"), name : "productCat1", products : ["productId1", productId2", productId3"]}
As i said about data access patterns, if you always read the Category-name and "Category-name" is something which is very infrequently updated then you can go for denormalizing with this two-way referencing by adding the product-category-name in the product:
Product = { _id = "productId1", name : "SomeProduct", price : "10", category : { ObjectId("111"), name:"productCat1" }
So, with embedding the documents, specific queries would be faster if no joins would be required, however other queries in which you need to access embedded details as stand-alone entities would be difficult.
This is a link from MongoDB which explains DB design for one-to-many scenario like you have with very nice examples in which you would realize that there are much more ways of doing it and many other things to think about.
http://blog.mongodb.org/post/88473035333/6-rules-of-thumb-for-mongodb-schema-design-part-3 (also has links for parts 1 & 2)
This link also describes the pros & cons for each scenario enabling you to reach a narrow down on a DB schema design.
It all depends on what queries you have in mind.
Suppose a product can only belong to one category, and one category applies to many products. Then, if you expect to retrieve the category together with the product, it makes sense to store it directly:
// products
{_id:"aabbcc", name:"foo", category:"bar"}
and if you expect to query all the products in a given category then it makes sense to create a separate collection
// categories
{_id:"bar", products=["aabbcc"]}
Remember that you cannot atomically update both the products and categories database (MongoDB is eventually consistent), but you can occasionally run a batch job which will make sure all categories are up-to-date.
I would recommend to think in terms of what kind of information will I often need, as opposed to how to normalize/denormalize this data, and make your collections reflect what you actually want.