MongoDB

Using MongoDB as a simple message board backend

Posted in MongoDB, python on December 25th, 2009 by jb55 – View Comments

I’ve been implemented a wakaba-like message board using MongoDB as a storage backend and it has been a real breeze so far. Most interactions with the database have been one liners in Python and there is little work involved with inserting new threads or replies. I’d have to say the worse part of the whole ordeal so far is the lack of integration with existing Python web frameworks. For that reason I decided not to use Django, which seems tightly coupled to sql solutions. I opted for a Werkzeug + Jinja2 + WTForms package called Glashammer which has worked quite well for me so far. Anyway, on to MongoDB…

Database structure

With my SQL habits my initial plan was to normalize all posts, with all threads and replies as MongoDB objects within a collection. It turns out this isn’t the best way to go about it. If the thread has a large amount of replies, the referenced lookup for each reply object is inefficient, and isn’t the MongoDBish way of doing things. What I found works best is a tree structure or a simple embedded array of replies:

{
  _id: ObjectId
  name: "jb55",
  topic: "What is this I don't even",
  msg: "I have important things to say",
  replies: [
    { name: "troll", msg: "tl;dr" },
    { name: "commentator", msg: "cool story bro" }
  ]
}

As you can see replies are embedded in the thread object. This makes pulling the thread from the database very quick, since the data will be together on the disk. You’ll probably want the thread and replies to have a reference to a user object, or a simple email depending on how sophisticated you want to go. For the purposes of my 4chan/wakaba-like forum it made sense not to store a user reference.

Some common tasks with PyMongo

All interactions between Python and MongoDB are pretty smooth and it doesn’t take much work to get up and running with insertions and updates.

Creating a new thread

db.threads.insert(
{'name': 'jb55', 'topic': 'My important topic', 'msg': 'blah blah'})

Adding new replies to a thread

reply = {'name': 'jb55', 'msg': 'This is my reply'}
db.threads.update({'_id': thread_id}, {'$push': {'replies': reply}})

Getting and displaying a thread

thread = db.threads.find({'_id': thread_id})
data["thread"] = thread
return render_to_response('template.htm', **data)

Easy isn’t it? No schemas, no hastle. In the interest of keeping this article short and sweet I think I’ll leave it at that for now. Try it out if you haven’t yet, it’s fun!