乐闻世界logo
搜索文章和话题

How can i save multiple documents concurrently in mongoose?

5 个月前提问
3 个月前修改
浏览次数48

6个答案

1
2
3
4
5
6

在Mongoose中,如果想要同时保存多个文档,可以使用Model.insertMany()方法。这个方法接受一个数组作为参数,数组中包含了要创建的多个文档的数据。使用insertMany不仅可以减少对数据库的请求次数,而且还能提高数据插入的效率。

下面是一个使用Model.insertMany()方法的例子,这里假设我们有一个名为User的模型,代表用户信息的文档结构。

javascript
const mongoose = require('mongoose'); const Schema = mongoose.Schema; // 定义User模型的Schema const userSchema = new Schema({ name: String, age: Number, email: String }); // 创建User模型 const User = mongoose.model('User', userSchema); // 准备要插入的用户数据 const users = [ { name: 'Alice', age: 25, email: 'alice@example.com' }, { name: 'Bob', age: 30, email: 'bob@example.com' }, { name: 'Carol', age: 22, email: 'carol@example.com' } ]; // 使用insertMany方法插入多个文档 User.insertMany(users) .then(docs => { console.log('Inserted documents:', docs); }) .catch(err => { console.error('Error inserting documents:', err); });

在这个例子中,我们首先定义了一个用户的Schema和对应的模型。然后创建了一个包含三个用户信息的数组。使用User.insertMany()方法,我们可以一次性将这三个用户信息作为文档插入到数据库中。这个方法返回的是一个Promise,它会在所有文档都成功插入后解析,并提供插入的文档作为参数。如果在插入过程中出现错误,Promise会被拒绝,并返回错误信息。

这种操作在需要批量导入数据时非常有用,比如在初始化数据库或者处理批量注册用户的场景。

2024年6月29日 12:07 回复

Mongoose does now support passing multiple document structures to Model.create. To quote their API example, it supports being passed either an array or a varargs list of objects with a callback at the end:

shell
Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) { if (err) // ... });

Or

shell
var array = [{ type: 'jelly bean' }, { type: 'snickers' }]; Candy.create(array, function (err, jellybean, snickers) { if (err) // ... });

Edit: As many have noted, this does not perform a true bulk insert - it simply hides the complexity of calling save multiple times yourself. There are answers and comments below explaining how to use the actual Mongo driver to achieve a bulk insert in the interest of performance.

2024年6月29日 12:07 回复

Mongoose 4.4 added a method called insertMany

Shortcut for validating an array of documents and inserting them into MongoDB if they're all valid. This function is faster than .create() because it only sends one operation to the server, rather than one for each document.

Quoting vkarpov15 from issue #723:

The tradeoffs are that insertMany() doesn't trigger pre-save hooks, but it should have better performance because it only makes 1 round-trip to the database rather than 1 for each document.

The method's signature is identical to create:

shell
Model.insertMany([ ... ], (err, docs) => { ... })

Or, with promises:

shell
Model.insertMany([ ... ]).then((docs) => { ... }).catch((err) => { ... })
2024年6月29日 12:07 回复

Mongoose doesn't have bulk inserts implemented yet (see issue #723).

Since you know the number of documents you're saving, you could write something like this:

shell
var total = docArray.length , result = [] ; function saveAll(){ var doc = docArray.pop(); doc.save(function(err, saved){ if (err) throw err;//handle error result.push(saved[0]); if (--total) saveAll(); else // all saved here }) } saveAll();

This, of course, is a stop-gap solution and I would recommend using some kind of flow-control library (I use q and it's awesome).

2024年6月29日 12:07 回复

Use async parallel and your code will look like this:

shell
async.parallel([obj1.save, obj2.save, obj3.save], callback);

Since the convention is the same in Mongoose as in async (err, callback) you don't need to wrap them in your own callbacks, just add your save calls in an array and you will get a callback when all is finished.

If you use mapLimit you can control how many documents you want to save in parallel. In this example we save 10 documents in parallell until all items are successfully saved.

shell
async.mapLimit(myArray, 10, function(document, next){ document.save(next); }, done);
2024年6月29日 12:07 回复

你的答案