使用 Mongoose 将文档移动到另一个集合

Posted

技术标签:

【中文标题】使用 Mongoose 将文档移动到另一个集合【英文标题】:Move a document to another collection with Mongoose 【发布时间】:2016-11-07 04:24:30 【问题描述】:

我正在尝试基于这种方法 Saving Mongoose object into two collections 将文档移动到 MongoDB 中的另一个集合。

在示例中,他展示了如何创建两个新对象。我的目标是将它从一个集合移到另一个集合。

更具体一点:在一个文档中,我有一个任务列表,这些任务最终会完成,然后应该在这个文档中移动到另一个数组。但是我需要能够查询所有未完成的内容,这应该可以通过两个集合来实现。

【问题讨论】:

【参考方案1】:

所以你必须注册 Schema 两次

let ChangeSchema = new Schema(
    title: String,
    version: Number
)

mongoose.model('First', ChangeSchema)
mongoose.model('Second', ChangeSchema)

然后你可以像这样交换它们

mongoose.model('First').findOne( _id: id , function(err, result) 

    let swap = new (mongoose.model('Second'))(result.toJSON()) //or result.toObject
    /* you could set a new id
    swap._id = mongoose.Types.ObjectId()
    swap.isNew = true
    */

    result.remove()
    swap.save()

    // swap is now in a better place

)

【讨论】:

我无法让这个解决方案发挥作用。我收到一个错误VersionError: No matching document found for id "58b1512b8f361b717254fa59" 几乎毫无意义我发现如果我先手动将文档注入到集合中,那么我就不会收到这样的错误,这让我相信我错过了关于 id 部分的步骤。谁能为这个解决方案添加更多细节? @stuffyjoelab 您首先需要有一个文档才能切换。 No matching document found for id "58b1512b8f361b717254fa59" 告诉你没有文件有他的id。 有点晚了,但是...除非架构中的属性_id 设置为String 类型,否则猫鼬会期望ObjectId。如果您的 id 是一个字符串并且 mongoose 需要一个对象 id,请使用 mongoose.Types.ObjectId(id),如有必要,请事先使用 mongoose.Types.ObjectId.isValid(id) 进行验证 正如@Ben 所说,猫鼬期待objectId 类型的参数。有一种方法可以通过ID mongoose.model.findById(_id)查找文档,这将返回所需的文档 @roskelld 将对象转换为普通对象(JSON)解决了这个问题。【参考方案2】:

上述解决方案是正确的,但如果“等待”removesave,则对于大量文档来说会太慢,否则可能会淹没实例。

这是半批量并行动作的简单改动

  // use "strict: false" so we won't have to declare schema in the script
  const First = mongoose.model('ActionsNewCollection', new mongoose.Schema(, collection: `first`, strict: false))
  const Second = mongoose.model('ActionsNewCollection', new mongoose.Schema(, collection: `second`, strict: false))


  const cursor = First.find().cursor();

  let moved_actions = []
  let moved_actions_ids = []
  for (let action = await cursor.next(); action != null; action = await cursor.next()) 

    let actions_json = action.toJSON()
    moved_actions.push(actions_json)
    moved_actions_ids.push(actions_json._id)

    // Every 100, stop and wait for them to be done
    if (moved_actions.length > 300) 
      let inserts = [Second.insertMany(moved_actions.slice(0,100)), Second.insertMany(moved_actions.slice(100,200)), Second.insertMany(moved_actions.slice(200))]
      let deletes = [First.deleteMany(_id:  $in: moved_actions_ids.slice(0,100)), First.deleteMany(_id:  $in: moved_actions_ids.slice(100,200)), First.deleteMany(_id:  $in: moved_actions_ids.slice(200))]
      await Promise.all(inserts)
      await Promise.all(deletes)
      moved_actions = []
      moved_actions_ids = []
    
  

【讨论】:

以上是关于使用 Mongoose 将文档移动到另一个集合的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Firestore -Flutter 中将所有文档从一个集合复制到另一个集合?

我如何将对象属性复制到另一个对象?

如何使用另一个集合 mongoose 查找子查询文档

使用聚合 mongodb mongoose 将集合子子文档与其他集合子文档连接起来

MongoDB/Mongoose:对同一集合中不同类型的文档使用不同的方案

将新字段添加到集合的所有文档中,将文档字段中的值添加到 MongoDB (Mongoose) 中,记录为 300K+