Using MongoDB as a simple message board backend
Posted in MongoDB, python on December 25th, 2009 by jb55 – 1 CommentI’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!