[MongoDB] exception: can't convert from BSON type EOO to Date の解決方法
MongoDB の aggregate で値が入ってない Date field に $year, $month を適用したところ exception: can’t convert from BSON type EOO to Date というエラーが発生して、解決した内容をご紹介します。
MongoDB に以下のようなデータが保存されている users collection があるとします。
// createdAt field が有る document
db.users.save( { name: 'hoge', createdAt: ISODate('2017-01-01') })
db.users.save( { name: 'fuga', createdAt: ISODate('2017-02-02') })
db.users.save( { name: 'mogu', createdAt: ISODate('2017-02-20') })
// createdAt field が無い document
db.users.save( { name: 'spam })
createdAt field に値が保存されていないにも関わらず $year, $month オペレーターを適用するとエラーが発生します。
db.users.aggregate({
$project: {
createdAt: 1
}
}, {
$group: {
_id: {
year: {
$year: "$createdAt"
},
month: {
$month: "$createdAt"
}
},
count: {
$sum: 1
}
}
});
// 以下、実行結果
assert: command failed: {
"ok" : 0,
"errmsg" : "can't convert from BSON type EOO to Date",
"code" : 16006
} : aggregate failed
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:16:14
assert.commandWorked@src/mongo/shell/assert.js:290:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1312:5
@(shell):1:1
2018-02-02T23:04:34.794+0900 E QUERY [thread1] Error: command failed: {
"ok" : 0,
"errmsg" : "can't convert from BSON type EOO to Date",
"code" : 16006
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:16:14
assert.commandWorked@src/mongo/shell/assert.js:290:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1312:5
@(shell):1:1
createdAt が Date Type なことをチェックするために $type: 9 を利用します。少し雑に比較するなら $ne: null や $exists: true なども使えます。
$year, $month など Date な値が渡ってくることを期待したオペレーターを使う場合は、$match で条件指定しておきましょうという話ですね。
db.users.aggregate({
$match: {
createdAt: {
$type: 9 // 雑に $ne: null や $exists: true も使える
}
}
}, {
$project: {
createdAt: 1
}
}, {
$group: {
_id: {
year: {
$year: "$createdAt"
},
month: {
$month: "$createdAt"
}
},
count: {
$sum: 1
}
}
});
// 以下、実行結果
{ "_id" : { "year" : 2017, "month" : 2 }, "count" : 2 }
{ "_id" : { "year" : 2017, "month" : 1 }, "count" : 1 }
以上、MongoDB の aggregate メソッドでエラーに遭遇した現場からお送りしました。