casbahでupsertする際のObjectIdに関する謎挙動
val id = new ObjectId
val where = DBObject("_id" $eq id) // <= (A)
val where = DBObject("_id" -> id) // <= (B)
val set = DBObject("_id" -> id)
db("collection").update(where, set, upsert=true)
(A)のパターンのときにエラーになる。
(B)はOK。
->
と$eq
で意味が違うのか??
find
はどっちでやっても結果同じだけど。。。
upsert
のときに発生。
update
のときに_id
変更NGなのは理解できるが。。。
失敗するパターン
val failed = { db: MongoDB =>
println("失敗するパターン")
val coll = db("sample")
coll.drop
val id = new ObjectId
val where = DBObject("_id" -> DBObject("$eq" -> id))
val set = DBObject("_id" -> id)
val result = coll.update(where, set, upsert=true)
/* ↑ここで例外発生
com.mongodb.WriteConcernException
serverUsed : "127.0.0.1:27017"
ok : 1
n : 0
updatedExisting : false
err : The _id field cannot be changed from {_id: { $eq: ObjectId('54fbcc2c3004a4267ff36eec') }} to {_id: ObjectId('54fbcc2c3004a4267ff36eec')}."
code : 16836
*/
println(result)
}
成功するパターン
val success = { db: MongoDB =>
println("成功するパターン")
val coll = db("sample")
coll.drop
val id = new ObjectId
val where = DBObject("_id" -> id) // <= 変更箇所
val set = DBObject("_id" -> id)
val result = coll.update(where, set, upsert=true)
// こっちは成功する
println(result)
}
cannot be changed
とか言ってるけど、upsert前にdropしてるからコレクション空っぽのはずだぞ。。。
回避策あるので深追いはしないが、、、みすてりー。
gistにコード全文。