はじめに
MongoDBやpymongoについては以前基本的な事を勉強した(Python/FlaskからMongoDBを扱うpymongo勉強内容メモ - Programming Log)ので、Webアプリを開発する場合の事を意識して触ってみる。
DBスキーマ
最近、達成日と達成コメントを残せるTodoリストのような簡単なWebアプリを開発している。このWebアプリでは以下の様な形式でMongoDBに保存しようと考えている。
{ 'TwitterID':u'__masapy__', 'TaskNum':3, 'Tasks':[ { 'TaskId':0, 'TaskTitle':u'Fishing', 'TaskDone':False, }, { 'TaskId':1, 'TaskTitle':u'Cycling', 'TaskDone':True, 'DoneComment':u'たのしかった!', 'DoneDate':u'2014-05-18' }, { 'TaskId':2, 'TaskTitle':u'Programming', 'TaskDone':False, } ] } ...他のユーザ
準備
>>> from pymongo import MongoClient >>> client = MongoClient() >>> db = client['UserDB'] # データベースを取得 >>> col = db.User # Userコレクションを取得
pymongoの重要なメソッド
find()
: 全部find({'key':'value'})
: 条件にマッチするのを全部取得find_one({'key':'value'})
: 条件にマッチするのを1つとってくるcount()
: findで取得したオブジェクトの数をカウントする
POST
ユーザ登録
>>> col.insert({'TwitterId':'__masapy__','TaskNum':0,'Tasks':[]})
タスク登録
>>> task_add = col.find_one({'TwitterId':'__masapy__'}) >>> task_num = task_add['TaskNum'] >>> task_add['Tasks'].append({'TaskId':task_num,'TaskTitle':u'Programming'},'TaskDone':False) >>> task_add['TaskNum'] += 1 >>> col.save(task_add) # DBに反映
GET
ユーザ一覧
>>> for user in col.find(): print user['TwitterId']
あるユーザのタスク一覧
>>> for task in col.find_one({'TwitterId':'__masapy__'})['Tasks']: print task['TaskId'], task['TaskTitle'], task['TaskDone']
実際の処理ではオブジェクトごとJinja2テンプレートに渡して、そちらでループすればいいので、
return render_template('tasks.html', tasks = col.find_one({'TwitterId':'__masapy__'})['Tasks'])
みたいな感じになると思う.
PUT
- 達成処理(TaskDoneをTrue,DoneCommentとDoneDateを追加)
>>> task_id = (POSTされたURIから更新したいtaskのTaskIdを決定) >>> done_comment = (達成コメント) >>> done_date = (達成日:Datetimeオブジェクト) >>> >>> user = col.find_one({'TwitterId':'__masapy__'}): >>> for task in user['Tasks']: >>> if task['TaskId'] == task_id: >>> task['TaskDone'] = True >>> task['DoneComment'] = done_comment >>> task['DoneDate'] = done_date >>> col.save(user)
ちゃんと動くか確かめてみた↓
In [2]: User = { ...: 'TwitterID':u'__masapy__', ...: 'TaskNum':3, ...: 'Tasks':[ ...: { ...: 'TaskId':0, ...: 'TaskTitle':u'Fishing', ...: 'TaskDone':False, ...: }, ...: { ...: 'TaskId':1, ...: 'TaskTitle':u'Cycling', ...: 'TaskDone':True, ...: 'DoneComment':u'たのしかった!', ...: 'DoneDate':u'2014-05-18' ...: }, ...: { ...: 'TaskId':2, ...: 'TaskTitle':u'Programming', ...: 'TaskDone':False, ...: } ...: ] ...: } In [3]: print User['TwitterID'] __masapy__ In [4]: for task in User['Tasks']: ...: if task['TaskId'] == 2: ...: task['TaskDone'] = True ...: task['DoneComment'] = u'たのしかった' ...: task['DoneDate'] = '2012-05-18' ...: else: ...: In [5]: print User { 'Tasks': [ {'TaskTitle': u'Fishing', 'TaskDone': False, 'TaskId': 0}, {'DoneDate': u'2014-05-18', 'TaskTitle': u'Cycling', 'TaskDone': True, 'DoneComment': u'\u305f\u306e\u3057\u304b\u3063\u305f\uff01', 'TaskId': 1}, {'DoneDate': '2012-05-18', 'TaskTitle': u'Programming', 'TaskDone': True, 'DoneComment': u'\u305f\u306e\u3057\u304b\u3063\u305f', 'TaskId': 2} ], 'TaskNum': 3, 'TwitterID': u'__masapy__' }
いいかんじ!
DELETE
アカウント削除
>>> col.remove({'TwitterId':'__masapy__'})
で可能だとは思うけど、念のためオブジェクトID指定した方がいいのかも?
>>> account_id = col.find_one({'TwitterId':'__masapy__'})['_id'] >>> col.remove({'u_id':account_id})
タスク削除
>>> task_id = (POSTされたURIから削除したいtaskのTaskIdを決定) >>> user = col.find_one({'TwitterId':'__masapy__'}): >>> for task in user['Tasks']: >>> if task['TaskId'] == task_id: >>> user['Tasks'].remove(tasks) >>> col.save(user) >>> break >>> else: >>> print u"そのようなタスクはありません"