4
\$\begingroup\$

This is my first implementation of MongoDB, much much more to come. This sheds light on some things like how I've structured my collection. I hope to gain feedback and insight from the community on best practices as well as do's and don'ts.

Givens

  • I have a website with multiple apps.
  • Each user can at one point signup / login for an app.
  • There is one MongoDB collection called users that will store all the information.
  • I want a log for each app that tracks users actions (signup, login, logout).

Example User Document

{
  "_id": ObjectId("5035b9fc0000005eed000002"),
  "apps": {
    "app0": {
      "log": [
        {
          "status": "signup",
          "created_at": ISODate("2012-08-23T05:05:00.872Z")
        },
        {
          "status": "login",
          "created_at": ISODate("2012-08-23T05:05:04.012Z")
        },
        {
          "status": "login",
          "created_at": ISODate("2012-08-23T05:05:06.236Z")
        }
      ]
    }
  },
  "user": "reggi"
}

This code is the first interaction with the user they put a small piece of information in and I have to determine whether they are already in the database or not. They can initiate the signup process more than once, so both the initial and update need to write the same log.

users.findOne({"username":req.query.user},function(err, post){
  if(typeof(post) == "undefined"){
    //username does not exist in users create it with this app instance
    users.save((function(){
      var object = {
        "username":req.query.user,
        "apps":{},
      };
      object.apps[appAlias] = {};
      object.apps[appAlias].log = [];
      object.apps[appAlias].log.push({
        status: "initiated-signup",
        created_at: new Date(),
      });
      return object;
    }()));
  }else{
    //username does exist in users create new apps object
    users.update({"_id":post._id},(function(){
      var object = {};
      object.$push = {};
      object.$push["apps."+appAlias+".log"] = {
        status: "initiated-signup",
        created_at: new Date()
      };
      return object;
    })())
  }
});

This is my first dabble with MongoDB. I'm using Mongolian.

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Code Review! Since you were wondering: the question is great, perfectly in the scope of Code Review. It's actually sad to see you didn't get an answer. \$\endgroup\$ Sep 18, 2012 at 9:30

1 Answer 1

2
\$\begingroup\$

While I cannot comment on your Node.js code, I can tell you that we're doing something very similar on a project that uses Mongo to store every bit of information for around 200 social profiles. In our case, we're doing something like:

foreach ($videos as $video) {
    $payload = ['$set'  => $defaults + $meta + $this->interjectTimestamps((array)$video)];

    if (isset($video['statistics'])) {
        // Maintain a log of statistics for each video
        $payload['$push'] = ['statistics_log' => ['execute_at_ts' => $meta['execute_at_ts'], 'statistics' => $video['statistics']]];
    }
    $coll->update(['_type' => 'video', 'id' => $video['id']], $payload, ['upsert' => true]);
}

From my research, this is fine. Mongo's $push works great for logs like this, but be wary, it can be difficult to query data in array's like this. If you plan on doing a lot of querying against a user's app's, it may be better to store this information in a separate collection.

On the flip side, this design can be crucial if you ever need to perform any calculations with data from both your User document and the nested log. In our case, we're doing MapReduce on data from the entire document, log and all.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.