Mongoose: Merge Model.create() & Model.insertMany() in one method

Created on 16 Mar 2017  路  12Comments  路  Source: Automattic/mongoose

[Feature]

Current behavior : as per docs, Model.create(doc(s), [callback]) does a MyModel(doc).save() when an array of documents is provided, whereas Model.insertMany() does the same thing but faster (_one operation to the server_).

So maybe stupid question, but why not merge those two methods so that create() behaves the same as insertMany() (thus performs better) when dealing with several docs + maybe deprecate insertMany() ?

Applies to latest version of Mongoose (4.9.0 at date of writing)

discussion new feature

Most helpful comment

if you put insertMany you cannot get createdAt and updatedAt time

All 12 comments

@Frosty-Z insertMany() doesn't trigger save middleware so they're slightly different.

@varunjayaraman is right, their implementations are sufficiently different to warrant being separate functions, plus we need insertMany() to fulfill the mongodb CRUD specification.

IMHO from a developer using Mongoose's perspective, a single, well documented create() endpoint would be simpler & less misleading.

This would still allow to keep different implementations & follow underlying MongoDB specs, for example by introducing an "options" parameter.

I would suggest for example

Model.create(doc, [callback]); // same as current
Model.create(arrayOfDocs, [callback]); // same as current

// would call MongoDB's insertMany() + Mongoose documentation would tell clearly
// that one operation is sent to server without using save() hook.
Model.create(arrayOfDocs, {"oneOperation": true}, [callback]); 

Only my personal opinion / 2 cents, ultimately it's your decision obviously 馃檪

Thanks for the suggestion. For now we need to stick with the current approach, because removing create() is backwards breaking and removing insertMany would break compatibility with the mongodb crud spec. May change in the future but unlikely, I'd rather avoid breaking existing code unless absolutely necessary :)

No problem ; thanks for your reply anyway ;-) I understand that breaking BC is a major concern ; on that point I agree with you 100%.

if you put insertMany you cannot get createdAt and updatedAt time

@ajithtunerlabs can you please clarify with code samples?

@vkarpov15 based on @mpacary comment. Here are some code samples to work with

const data = [{ name: 'Johnson', text: 'First test todo' }, { name: 'Abdullahi', text: 'Second test todo' }]; // operation is saved to the server without the save() hook. Model.create(data, {"oneOperation": true}).then((docs)=>{ console.log(docs); });

@vkarpov15 Here are some code samples

const data = [{
   name: 'Johnson',
   text: 'First test todo'
}, {
   name: 'Abdullahi',
   text: 'Second test todo'
}];
Model.insertMany(data).then((docs)=>{
  console.log(docs);
});

If you do this you cannot get updateAt and createdAt field. Create will give you those fields but I don't want to use create functionality. Thanks

@ajithtunerlabs which version of mongoose are you using? We have test coverage for timestamps with insertMany unless I'm much mistaken.

@vkarpov15 I am using

"mongoose": "^5.0.17"

If you try to create multiple documents using insertMany you won't get the timestamp(createdAt, updatedAt) in those created fields.

@ajithtunerlabs ^5.0.17 is not a version. Depending on if you have package-lock.json, that can mean any version from 5.0.17 to 5.4.16. The below script works fine in 5.4.16 and shows that insertMany() does add timestamps to the documents. Please modify the below script to demonstrate your issue.

const assert = require('assert');
const mongoose = require('mongoose');
mongoose.set('debug', true);

const GITHUB_ISSUE = `gh5081`;
const connectionString = `mongodb://localhost:27017/${ GITHUB_ISSUE }`;
const { Schema } = mongoose;

run().then(() => console.log('done')).catch(error => console.error(error.stack));

async function run() {
  await mongoose.connect(connectionString);
  await mongoose.connection.dropDatabase();

  const Model = mongoose.model('gh5081', new Schema({ name: String }, { timestamps: true }));

  await Model.insertMany([{ name: 'a' }, { name: 'b' }]);

  console.log(await Model.find());
}
Was this page helpful?
0 / 5 - 0 ratings