Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm just starting out on an application and I've heard some good things about MongoDB so I thought I'd give it a crack in this new project to see how well it works.

Please bear in mind that prior to this I've only ever really used RDBMSs like MySQL, Oracle, etc. so it's been quite an adjustment to think of this in a more document-oriented fashion which is why I figured I should ask for help now before I become hopelessly lost.

The basic context behind this application is that it's a "Guild" system. A basic guild consists of

  • A leader
  • Basic metadata (name, description, tagline...etc.)
  • Ranking hierarchy (master, officer, fresher), these are unique to each guild so that the master can create their hierarchy as they like, each rank has certain 'permissions' associated with it.
  • Members (sub-users of the application, explained later). Each sub-user can only belong to one guild.

At the moment I've created a collection called users, which contains all the User documents, I figured that it'd be better to have these separate from the eventual Guild documents rather than embedded as I'll probably need to use them in other areas of the application. The basic User document will look something like:

{
    _id:            ObjectId,
    email:          String,
    password:       String,
    displayName:    String,
    dateJoined:     Date,
    characters:     Array({ _id: ObjectId, uniqName: String, ... })
    ...
}

Basically each registered User gets to add multiple characters to their account, these characters are the ones that actually get the Guild affiliation rather than the overarching User, this is what's making it quite tricky to structure.

My basic idea for the Guild document was something like the following:

{
    _id:            ObjectId,
    leader_id:      ObjectId(references a `character` in a `User` document),
    name:           String,
    tagline:        String,
    description:    String,
    rankings:       Array({
        _id:            ObjectId,
        title:          String,
        weight:         Integer, // for ordering
        canAddMembers:  Boolean,
        canDelMembers:  Boolean,
        // ...additional permissions and stuff per-ranking here
    }),
    members: Array({
        character_id:   ObjectId(references a `character` in a `User` document),
        ranking_id:     ObjectId(references a `ranking` in the `rankings` array),
        dateJoined:     Date
    })
}

Which seemed okay-ish to me. The main problem I'm forseeing is that there's no straightforward way to find all Guilds that a User's characters are a part of.

An example use case: The User's profile, it should show all of their characters and their Guild affiliations, won't this be a rather slow operation as it'll need to search every single Guild's members array for the character_id? This seems incredibly expensive, especially if there are a lot of guilds with large memberships.

My next though was to simply add a guild_id field the character sub-document, instead of storing the members in the Guild document. This obviously leads to another problem: Viewing all of the Guild's members, you'd then need to search every User's characters array for the guild_id field. Seems about as expensive as the first solution to me (if not more so as there's likely to be a lot more User documents than Guild documents).

The only solution I could see that works for both use cases is to simply do both: Have a members array in the Guild document, and maintain a guild_id field in the characters sub-document. However this really goes against the grain; now I need to maintain two fields for any membership changes rather than just one which seems like it'd breed database inconsistencies (it relies extensively on good application-level code).

share|improve this question
    
The tail seems to be wagging the dog a bit. There isn't much semi-structuring in the data definitions and there are a lot of formal relationships and those formal relationships are programmer defined rather than user defined. The semi-structured data occurs out toward the leaves rather than the root - it's in the game play logic not site/user/game-administration. NoSQL doesn't seem to fit the way you're looking at the high levels of the application. Because the DBMS isn't designed around user generated documents, semi-structured data isn't bubbling up organically to drive the design. –  ben rudgers Oct 28 '14 at 13:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.