Mongoose#Documentのsaveメソッドで更新できないとき

#概要

仕事でMongooseを使ったプロジェクトをやっていたときに、ドキュメントが更新されない事象に遭遇。
そのまんまは書けないが、モデルは大体こんな感じで

const Photo = mongoose.Model('Photo', {
  // オーナユーザID
  owner: ObjectId,
  // 写真のメタ情報
  metadata: Object
})

スキーマがきっちり決まっていない外部のJSON(Object)をそのままDBに突っ込むということをしていた。

ちなみに保存処理はこんな感じ。

const photos = await Photo.find({/* てきとうなクエリ */})

return Promise.all(photos.map(photo => {
  photo.metadata.tags = photo.metadata.tags ? ['myawesomeapp', ...photo.metadata.tags] : ['myawesomeapp']

  return photo.save()
})

しかし実行してデータを確認してみるとmetadata.tagsmyawesomeappがない...。

#原因

Mongooseがドキュメントに変更があったと認識していない為、保存処理が走っていない模様。

#対処

Document#markModifiedを呼んでからsaveメソッドを呼ぶ。

さっきの例だとこんな感じ。

const photos = await Photo.find({/* てきとうなクエリ */})

return Promise.all(photos.map(photo => {
  photo.metadata.tags = photo.metadata.tags ? ['myawesomeapp', ...photo.metadata.tags] : ['myawesomeapp']

  photo.markModified('metadata') // 追加

  return photo.save()
})

#参考

https://stackoverflow.com/a/39823651
https://qiita.com/Eiryyy/items/2b287023256e67172203