mongoDBで日付を扱うときの注意点
2017/01/20
mongoDBに格納していたデータをaggregateを使って日付単位で集計しようとしたら、「can’t convert from BSON type String to Date**」**というエラーが発生したのでその時の対処法です。
また、その際にmongoDBの日付の扱いについていろいろ調べたため内容をまとめます。
日付を文字列として格納するとaggregateで日付として扱えない
日付を文字列としてmongoDBに格納した場合、aggregateで期間指定しようとしてもエラーになるようです。
> db.test.insert({"date":"Sat Aug 22 21:03:40 GMT+09:00 2015"});
> db.test.aggregate({$project:{year:{$year:"$date"}}})
assert: command failed: {
"errmsg" : "exception: can't convert from BSON type String to Date",
...
日付をDate型(type 9)で格納すると上手くいきます。下の例でいうと参照した際に「ISODate(“2015-10-10T12:24:19.508Z”)」となっているとDate型となります。他は文字列として入ってしまうようでNGです。
> db.test.insert({"date":new Date("Sat Oct 10 21:24:19 GMT+09:00 2015")});
> db.test.insert({"date":"Sat Aug 22 21:03:40 GMT+09:00 2015"});
> db.test.insert({"date":"2015-08-26T12:03:40Z"});
> db.test.find()
{ "_id" : ObjectId("561903732489c6fd1a587f1c"), "date" : ISODate("2015-10-10T12:24:19Z") }
{ "_id" : ObjectId("561903b32489c6fd1a587f1d"), "date" : "Sat Aug 22 21:03:40 GMT+09:00 2015" }
{ "_id" : ObjectId("5619140b5c1d5c59181ae41a"), "date" : "2015-08-26T12:03:40Z" }
> db.test.aggregate({$match: {"date":{$type:9}}},{$project:{year:{$year:"$date"}}})
{ "_id" : ObjectId("561903732489c6fd1a587f1c"), "year" : 2015 }
MongoDBは日付をISODateとして扱うため、都度日本時間に変換が必要
MongoDBは格納した日付をISODate(標準時)として扱うため、日本時間に直すには日付を取り出した後に9時間加算する必要があります。
nodejsから日付をInsertするときの型の扱われ方
mongoozeを使用するとスキーマ定義で型を指定できますが、通常のMongoDBドライバを使用した場合は型の指定ができないため、書き方によっては日付が文字列として格納されるため注意が必要です。
var MongoClient = require('mongodb').MongoClient;
var MONGODB_URI = 'mongodb://xxx:27017/test';
var db;
MongoClient.connect(MONGODB_URI, function(err, database) {
if(err){
}
db = database;
});
var coll = db.collection('test');
//↓文字列として格納される
coll.insert({"date":"Sat Aug 22 21:03:40 GMT+09:00 2015"});
//↓日付型として格納される
coll.insert({"date":new Date("Sat Aug 22 21:03:40 GMT+09:00 2015")});
//↓文字列として格納される
tmp = JSON.parse('{"date":"Sat Aug 23 21:03:40 GMT+09:00 2015"}')
coll.insert(tmp);
//↓日付型として格納される
tmp = JSON.parse('{"date":"Sat Aug 23 21:03:40 GMT+09:00 2015"}')
tmp.date = new Date(tmp.date);
coll.insert(tmp);