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
Related
Given there is a one to many relationship between users and comments, and all ids are provided to be unique;
what are the considerations between naming the operation as:
DELETE /users/{user_uuid}/comments/{comment_uuid}
or
DELETE /comments/{comment_uuid}?
In the former user_uuid is redundant as it's not needed to delete a comment. Is it worth keeping user_uuid just to make the urls looks RESTful?
Both work fine for well structured RESTful resource--long as the comment_uuid is indeed a uuid. Neither hint at the underlying implementation or strikes me as screaming this is an RPC service :)
Whatever you choose, rule #1... Keep it consistent.
That being said, I prefer the first one as it reinforces semantic information that this is a user comment. I can see that and know pretty much what I'm getting back, without making a request.
Comment is a bad one to show a counter case, because most comments are from users, but think about this... conceivably, you could have some other type of entity that leaves comments, imagine registering bots in your system /bot/{bot_uuid},
Now if you go with just /comment you did you just delete a user or bot comment?
Compare this as you're scanning code vs /bot/{bot_uuid}/comment/{comment_uuid}. The more verbose is a lot clearer IMOP.
Finally, if someone provides a get request for a specific comment /users/{user_uuid}/comments/{comment_uuid} I know the URL for the user, just drop the omment part. Sure, most might guess, /user/{user_uuid}, but like I said, user and comment are bad examples, as you get more non-typical resource name it becomes less obvious. The thing is if you're alway's explicit, you don't have to worry when the resources looks like these:
/widget/{widget_uuid}/contrawidget/{co_uuid}/parts/{part_uuid}
/spaceframe/{spaceframe_uuid}/parts/{part_uuid}
Now would you just do parts:
/parts/{part_uuid}
probably nots as it could be confusing to the consumer
Is it worth keeping user_uuid just to make the urls looks RESTful?
No. The business value that you get from making the identifiers look RESTful is indistinguishable from zero.
You might do it for other reasons: URI design is primarily about making things easier for humans. As far as the machines are concerned, all of the URI could just be UUIDS with no other hints.
That said, there is something important to consider....
/users/{user_uuid}/comments/{comment_uuid}
/comments/{comment_uuid}
These are different identifiers; therefore, as far as the clients are concerned, they are different resources. This means that, as far as clients are concerned, they are cached separately. Invalidating one does not invalidate the other.
(Of course, other clients, unaware that the DELETE happened, will continue using cached copies of both resources. Cache invalidation is one of the two hard problems).
I think that what your question is a design question and not a RESTful question as #ray said, and like for all design question the answer is... depends.
I prefer the first one also, because the comment (as I understand a comment) could not exist without a user.
But for this kind of questions I use the Entity-Control-Boundary Pattern (EBC) it basically propose a form to interact with your application in the context of certain entities, not using all the entities of the system, just the key ones, I generally use this as my rule to identify the paths that make more sense.
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.
I just wanted to validate my data structure.
It seems a bit convoluted to me, maybe it can be simplified?
Questions are grouped into chapters.
For each question, only one answer per session is possible.
The purpose is to be able to compare / analyze answers to the same questions (by different users or by the same users at different times, i.e. with different sessions).
A template, being a collection of chapters & questions, should not have to be replicated, if chapters and questions are the same.
(That would be necessary if Answer did not have a relationship to Session.)
Is the relationship from Answer back to Session the right strategy?
What else would you improve to simplify the model?
Thank you!
EDIT
Follow-up clarification:
The Answer is not static (e.g. "right" answer, "solution"), but some text the user inputs. It is more like a "questionnaire" than a "quiz". The answer has quantitative attributes that can be analyzed.
As stated, one question can have only one answer within a session. Because questions can indirectly belong to more than one session (via (NSSet*) question.chapter.template.sessions), they could have more than one answers and thus need a to-many relationship.
The typical scenario: User starts a new session with a certain template and fills out the answers. Then he can look at the analysis of the results and compare those with the results of other sessions that use the same template.
EDIT 2
The snapshot of the data model including attributes
honestly, this is what I would do instead of your structure, but I don't know what the purpose of the each entity because I'm not able to find out from their simple names.
this is just an idea to resolve the loop.
you can still reach all templates and all answers from the session, not directly but it does not make your life much harder.
UPDATE:
at the first and second sight, for me, it seems the Session entity is just an extra entity only here. honestly you would not need it, if you concatenate with the Template (aka Questionnaire) entity.
you have to add a many-to-many relationship between the Template and User (you can do it, don't worry about it). using this way, from each template you can reach all answers as well, and you won't have any loop.
Despite the really helpful effort by the part of #holex - the best way still seems to be to stick with my design. The simplifications I had hoped for have not materialized.
I know this question is not about particular problem I have. It's rather question to GWT SDK team. As far as I remember StackOverflow is now their official communication channel with engineering community :)
Problem:
For aliased editors such as ValueBoxEditorDecorator you'll receive duplicate errors in your HasEditorErrors.showErrors() - one for ValueBoxEditorDecorator itself and another one for nested ValueBoxEditor. Current implementation of ValueBoxEditorDecorator iterates through list of errors and rejects ones that don't belong to nested editor. It looks like a hacky workaround to me :)
Question:
I think duplicates should be discarded somewhere earlier, for example in SimpleViolation.pushViolations or DelegateMap.of or ErrorCollector.endVisit.
Initially I thought why not just keep one delegate per unique EditorContext.getAbsolutePath and drop the rest. Then I realized that perhaps there is a use-case when ValueBoxEditorDecorator and its inner ValueBoxEditor would get different errors although I can't come up with the scenario how it can happen due to my short-time knowledge of gwt's sources.
So here is what I think. Why don't we use map in ErrorCollector.errorStack instead of List where the key will be combination of EditorError.getAbsolutePath() and EditorError.getUserData() ? It would solve two issues IMO:
We won't need to filter out dupkicate errors in our editors.
ErrorCollector.visit() won't assume that editors like this one are traversed in hierarchical order. I don't see anywhere in documentation that visitors would always work that way.
What do you think ?
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.