日時を使った検索がうまくいかない(回避案)
前回(http://d.hatena.ne.jp/stog/20100526/1274899622)の続き。
MongoDBで日時を使った検索をするとき、1970-01-01より前の日付がうまく扱えない件について、自分が使い方を間違っているのか、そういう仕様なのか未だに分かっていない。。
なので、以下のように日付をタイムスタンプとして扱えば良いのかも。
テストデータ
dummy.tsv
name type sex birthday おがわ human M 1980/11/03 たかはし human F 1974/02/20 たなか human M 2003/01/15 さとう human F 1960/10/05 ポチ dog F 2005/06/07 タロ dog M 1995/08/08 タマ cat F 2008/12/24 ミケ cat M 1998/12/25 John human M 1970/01/01 Michael human M 1940/08/09 Robert human M 1999/05/20 David human M 2009/12/05 James human M 1969/12/31 Mary human F 1985/04/10 Barbara human F 1955/10/15 Anne human F 2001/01/20 Maria human F 1945/09/25 Susan human F 1977/11/30
日付をタイムスタンプに変換してDBに保存する。
test_insert.py
#!/usr/bin/env python # -*- coding:utf-8 -*- import csv import datetime import calendar import pymongo conn = pymongo.Connection() db = conn["mytest"] coll = db["members2"] fh = open("./dummy.tsv", "r") contents = csv.DictReader(fh, delimiter='\t') for data in contents: year, month, day = [int(x) for x in data["birthday"].split('/')] dt = datetime.datetime(year, month, day) data["birthday"] = calendar.timegm(dt.timetuple()) coll.insert(data) fh.close() conn.disconnect() print "coll.count() =", coll.count()
DBから取得したタイムスタンプを日付に変換して出力する。
test_find.py
#!/usr/bin/env python # -*- coding:utf-8 -*- import csv import datetime import calendar import pymongo def timestamp2date(timestamp): return datetime.datetime.utcfromtimestamp(timestamp) def printdata(data): print "name: %(name)s,\ttype: %(type)s,\tsex: %(sex)s,\tbirthday: %(birthday)s" % data conn = pymongo.Connection() db = conn["mytest"] coll = db["members2"] # 検索条件なし print "find()" print "----------------------------------------" for data in coll.find(): data['birthday'] = timestamp2date(data['birthday']) printdata(data) print # 犬を検索 print "find({'type':'dog'})" print "----------------------------------------" for data in coll.find({'type':'dog'}): data['birthday'] = timestamp2date(data['birthday']) printdata(data) print # 人間ではなく、性別がオスであるものを検索 print "find({'type':{'$ne':'human'}, 'sex':'M'})" print "----------------------------------------" for data in coll.find({'type':{'$ne':'human'}, 'sex':'M'}): data['birthday'] = timestamp2date(data['birthday']) printdata(data) print # 誕生日が2000-01-01以降のものを検索したい print "find({'birthday': {'$gte': datetime.datetime(2000, 1, 1)}})" print "----------------------------------------" for data in coll.find({'birthday': {'$gte': calendar.timegm(datetime.datetime(2000, 1, 1).timetuple())}}): data['birthday'] = timestamp2date(data['birthday']) printdata(data) print # 誕生日でソートしたい print "find().sort('birthday')" print "----------------------------------------" for data in coll.find().sort('birthday'): data['birthday'] = timestamp2date(data['birthday']) printdata(data) print conn.disconnect()
以下が実行結果。
$ python test_insert.py coll.count() = 18 $ python test_find.py find() ---------------------------------------- name: おがわ, type: human, sex: M, birthday: 1980-11-03 00:00:00 name: たかはし, type: human, sex: F, birthday: 1974-02-20 00:00:00 name: たなか, type: human, sex: M, birthday: 2003-01-15 00:00:00 name: さとう, type: human, sex: F, birthday: 1960-10-05 00:00:00 name: ポチ, type: dog, sex: F, birthday: 2005-06-07 00:00:00 name: タロ, type: dog, sex: M, birthday: 1995-08-08 00:00:00 name: タマ, type: cat, sex: F, birthday: 2008-12-24 00:00:00 name: ミケ, type: cat, sex: M, birthday: 1998-12-25 00:00:00 name: John, type: human, sex: M, birthday: 1970-01-01 00:00:00 name: Michael, type: human, sex: M, birthday: 1940-08-09 00:00:00 name: Robert, type: human, sex: M, birthday: 1999-05-20 00:00:00 name: David, type: human, sex: M, birthday: 2009-12-05 00:00:00 name: James, type: human, sex: M, birthday: 1969-12-31 00:00:00 name: Mary, type: human, sex: F, birthday: 1985-04-10 00:00:00 name: Barbara, type: human, sex: F, birthday: 1955-10-15 00:00:00 name: Anne, type: human, sex: F, birthday: 2001-01-20 00:00:00 name: Maria, type: human, sex: F, birthday: 1945-09-25 00:00:00 name: Susan, type: human, sex: F, birthday: 1977-11-30 00:00:00 find({'type':'dog'}) ---------------------------------------- name: ポチ, type: dog, sex: F, birthday: 2005-06-07 00:00:00 name: タロ, type: dog, sex: M, birthday: 1995-08-08 00:00:00 find({'type':{'$ne':'human'}, 'sex':'M'}) ---------------------------------------- name: タロ, type: dog, sex: M, birthday: 1995-08-08 00:00:00 name: ミケ, type: cat, sex: M, birthday: 1998-12-25 00:00:00 find({'birthday': {'$gte': datetime.datetime(2000, 1, 1)}}) ---------------------------------------- name: たなか, type: human, sex: M, birthday: 2003-01-15 00:00:00 name: ポチ, type: dog, sex: F, birthday: 2005-06-07 00:00:00 name: タマ, type: cat, sex: F, birthday: 2008-12-24 00:00:00 name: David, type: human, sex: M, birthday: 2009-12-05 00:00:00 name: Anne, type: human, sex: F, birthday: 2001-01-20 00:00:00 find().sort('birthday') ---------------------------------------- name: Michael, type: human, sex: M, birthday: 1940-08-09 00:00:00 name: Maria, type: human, sex: F, birthday: 1945-09-25 00:00:00 name: Barbara, type: human, sex: F, birthday: 1955-10-15 00:00:00 name: さとう, type: human, sex: F, birthday: 1960-10-05 00:00:00 name: James, type: human, sex: M, birthday: 1969-12-31 00:00:00 name: John, type: human, sex: M, birthday: 1970-01-01 00:00:00 name: たかはし, type: human, sex: F, birthday: 1974-02-20 00:00:00 name: Susan, type: human, sex: F, birthday: 1977-11-30 00:00:00 name: おがわ, type: human, sex: M, birthday: 1980-11-03 00:00:00 name: Mary, type: human, sex: F, birthday: 1985-04-10 00:00:00 name: タロ, type: dog, sex: M, birthday: 1995-08-08 00:00:00 name: ミケ, type: cat, sex: M, birthday: 1998-12-25 00:00:00 name: Robert, type: human, sex: M, birthday: 1999-05-20 00:00:00 name: Anne, type: human, sex: F, birthday: 2001-01-20 00:00:00 name: たなか, type: human, sex: M, birthday: 2003-01-15 00:00:00 name: ポチ, type: dog, sex: F, birthday: 2005-06-07 00:00:00 name: タマ, type: cat, sex: F, birthday: 2008-12-24 00:00:00 name: David, type: human, sex: M, birthday: 2009-12-05 00:00:00
とりあえず、うまくいったっぽい。