arc
arc

Reputation: 4691

Move a document to another collection with Mongoose

I'm trying to move a document to another collection in MongoDB based on this approach Saving Mongoose object into two collections.

In the example he shows how to create two new objects. My goal is to move it from one collection to another.

To be a bit more specific: In a document I have a list of tasks which eventually get completed and should then be moved inside this document to another array. However I need to be able to query all the unfinished and this should be possible with two collections.

Upvotes: 7

Views: 11517

Answers (2)

SnirD
SnirD

Reputation: 716

The solution above is correct but will be too slow for a massive amount of documents if "awaited" for remove and save, or may flood an instance if it doesn't.

Here's a simple alteration for semi-bulk parallel action

  // 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 = []
    }
  }

Upvotes: 0

arc
arc

Reputation: 4691

So you have to register the Schema twice

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

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

Then you can swap 'em like this

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

})

Upvotes: 15

Related Questions