How deep should I embed with Mongoid? - mongodb

Hi I'm new to mongoDB and Mongoid and am little bit confused on when to use embedded documents and how deep to embedd.
So a fictional example:
Library collection has_many :books, which embeds_many :pages, which embeds_many :sections
Since I cannot work with say a Section directly I have to go trough books.pages.sections, right?
This would result in this route, libraries/:id/books/:id/pages/:id/sections/:id
Which seems a little bit crazy, best practice would be to only nest one level deep, right?
One way would be to have the route pages/:id/sections/:id and then stick the bookid in the request?
Would it be harder to query on say, sections? For example if I need to find all the books where sections has tag x?
However if I don't embedd all the way I would have an extra query?
Can someone shed some light? Thanks.

First of I believe that no one can give you the right answer about how deeply you should embed documents. It is highly dependent on your concrete project requirements. In general you should answer some questions to choose appropriate schema design:
Will users concurrently update same object in collection? (or what would my boss say if clients lost their updates)
Do I need support atomic operations?
Do I need to independently show nested collections or are they queried with the parent?
Do I need to sort embedded objects?
Do I need to query on embedded objects?
If you will answer 1,2-true; 3 I need show them independently (different page); 4,5 - true then i am sure that embedding will be some kind of pain in your ass.
Extra queries should not be a problem I guess.

Related

nosql wishlist models - Struggle between reference and embedded document

I got a question about modeling wishlists using mongodb and mongoose. The idea is I need a user beeing able to have many different wishlists which contain many wishes, each wish making a reference to a single article
I was thinking about it and because a wishlist only belong to a single user I thought using embedded document for that.
Same for the wish beeing embedded to a wishlist.
So I got something like that
var UserSchema = new Schema({
...
wishlists: [wishlistSchema]
...
})
var WishlistSchema = new Schema({
...
wishes: [wishSchema]
...
})
but my question is what to do with the article ? should I use a reference or should I copy the article's data in an embedded document.
If I use embedded document I got an update problem. When the article's price change, to update every wish referencing this article become a struggle. But to access those wishes's article is a piece of cake.
If I use reference, The update is not a problem anymore but I got a probleme when I filter the wish depending on their article criteria ( when I filter the wishes depending on a price, category etc .. ).
I think the second way is probably the best but I don't know how if it's possible to build a query to filter the wish depending on the article's field. I tried a lot of things using population but nothing works very well when you need to populate depending on a nested object field. ( for exemple getting wishes where their article respond to certain conditions ).
Is this kind of query doable ?
Sry for the loooong question and for my bad English :/ but any advice would be great !
In my experience in dealing with NoSQL database (mongo, mainly), when designing a collection, do not think of the relations. Instead, think of how you would display, page, and retrieve the documents.
I would prefer embedding and updating multiple schema when there's a change, as opposed to doing a ref, for multiple reasons.
Get would be fast and easy and filter is not a problem (like you've said)
Retrieve operations usually happen a lot more often than updates and with proper indexing, you wouldn't really have to bother about performance.
It leverages on NoSQL's schema-less nature and you'll be less prone restructuring due to requirement changes (new sorting, new filters, etc)
Paging would be a lot less of a hassle, and UI would not be restricted with it's design with paging and limit.
Joining could become expensive. Redundant data might be a hassle to update but it's always better than not being able to display a data in a particular way because your schema is normalized and joining is difficult.
I'd say that the rule of thumb is that only split them when you do not need to display them together. It is not impossible to join them back if you do, but definitely more troublesome.

does mongodb support subcollections

Is there such a concept as subcollections in mongo, something like a subdocument but supports the full crud api? I would like to organize my db to perform queries like this:
db.games.pong.leaderbords.find({score:{'$gt':99}})
In other words is there any hierarchy to collections or must I create a fully descriptive name for each collection, as in:
db.pongLeaderboard.find({score:{'$gt':99}});
EDIT: As Nicolas pointed out the dot notation is allowable. What I meant to ask is can I do this and have games and pong be proper collections in their own right so I could still do something like
db.games.find({name:'pacman'})
It's perfectly legal for collection names to contain the . character, so it's entirely possible to organise your data such that your first query is correct.
I'm fairly sure that creating the collection games.pong.leaderbords does not create games, games.pong or pong though, so this might not answer your problem.
This type of question is terribly easy to answer for yourself though - just type your query in MongoDB and see what happens. If it fails, it's not possible. If it doesn't, it's possible. MongoDB is good that way. Not only does that give you a definite answer, it also gives you an immediate answer without having to wait for someone to try and type your query and post the result.
What I meant to ask is can I do this and have games and pong be proper collections in their own right so I could still do something like
If I understand you right then no. Those two "subcollections" will have no reference to each other as such, unless you have actually created a games collection with data in (db.games.ping.xx doesn't count) then this will not work.

Is there a way to link to Meteor.Collections() together?

I have finally go around to trying out meteor and I think it's really cool so far. I have been trying to link two Meteor.Collections() together like in a relational database.
For example let's say that the user enters and animal type like "Dog" and then other users could input types of dogs like "Doberman", "Labrador", etc.
Thanks in advance
Basically, the idea behind a document based Databases like MongoDB is not to try to imitate relational DBs. Try to see if you can add (embed) the types as a child of the animal type in the same collection instead of creating a link between two collections.
With that said, there is still a way to link between to collections - The way to do that is outside of queries - meaning you get the results from one query and then pass them to the other query as paramaters (as you can see it's not an efficient way).
More background info can be found at - http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-EmbeddingandLinking
or - MongoDB and "joins"

MongoDB schema design -- Choose two collection approach or embedded document

I am trying to design a simple application where in I have two entities Notebook and Note. So Notebook can contain multiple Notes.In RDBMS I could have two tables and have One to Many
relationship between them. I am not sure in MongoDB whether I should not take a two collection
approach or I should embed notes in Notebook collection. What would you suggest?
That seems like a perfectly reasonable situation to use a single collection called Notebook, and each Notebook document contains embedded Notes. You can easily index on embedded documents.
If a Notebook document has a 'notes' key, and value is a list of notes:
{
"notes": [
{"created_on": Date(1343592000000), text: "A note."}
]
}
# create index
db.notebook.ensureIndex({"notes.created_on" : -1})
My opinion is to try and embed as much as possible, and then choose to reference another collection via an id as a second option when the reference needs to be to a more general set of data that is shared and might change. For instance, a collection of category documents which many other collections reference. And the category can be updated over time. But in your case, a note should always belong to a note book
You should ask yourself what kind of queries you will need to run on it. The "by default" approach is to embed them, but there are cases (that will depend on how you plan on using them) where a more relational approach is applicable. So the simple answer is "probably, but you should probably think about it" :)

Best Practice Mongoid:NestedResources

I'm starting off with a small Rails3:MongoDB:Mongoid project and came along some questions that's nature is more architectural.
When to use nested resources, and how deep to nest?
I'm not a friend of nested routes at all, but they become handy if not stacked deeper than 2 resources and document oriented databases like MongoDB seem to be a perfect target for nesting at all since documents itself are nested.
So my first question was: Should I use nested routes in case of a references_many <=> referenced_in association?
I tried, and since ActiveRecord's "build" is not existant, the whole controller stuff brake down to something that looked much nicer without nesting at all and doing all the stuff manually.
Am I wrong? Should I nest the routes of such associations too?
After that I came to my first embedded documents, and argued myself: Hey, this begs for nesting the routes. Some iterations later I ended up with 4 instead of 2 documents, every embedded in one of the others. So nesting the routes led to URL's I did'nt really like.
So the question to the already MongoDB-experienced user is: should I nest? And if yes, under what circumstanced and how deep?
Greets
J.
I had a similar set of questions. Ryan Bates created an excellent Railscast about Mongoid after you made this post. There is a section covering associations and when to use the embedded_* idiom versus the references_* idiom. It has examples of both. Hopefully you've had a chance to check out the Railscast. If not, here is the link to the associated ASCIIcast:
http://asciicasts.com/episodes/238-mongoid
Everything I've read about nesting resources with respect to Mongoid, or ActiveRecord states a best practice of nesting no more than one level deep.
http://weblog.jamisbuck.org/2007/2/5/nesting-resources