Mongoose / Node.js에서 여러 문서를 동시에 저장하려면 어떻게해야합니까?
지금은 저장을 사용하여 단일 문서를 추가합니다. 단일 객체로 저장하려는 문서 배열이 있다고 가정합니다. 단일 함수 호출로 모두 추가 한 다음 완료되면 단일 콜백을받는 방법이 있습니까? 모든 문서를 개별적으로 추가 할 수 있지만 모든 작업이 완료되면 콜백을 관리하는 것은 문제가 될 수 있습니다.
Mongoose에는 아직 대량 삽입이 구현되지 않았습니다 ( 문제 # 723 참조 ).
저장할 문서의 수를 알고 있으므로 다음과 같이 작성할 수 있습니다.
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();
물론 이것은 임시 방편 솔루션이며 어떤 종류의 흐름 제어 라이브러리를 사용하는 것이 좋습니다 (저는 q를 사용 하고 굉장합니다).
Mongoose는 이제 여러 문서 구조를 Model.create에 전달하는 것을 지원 합니다. API 예제를 인용하기 위해 끝에 콜백이있는 객체의 배열 또는 varargs 목록을 전달할 수 있습니다.
Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
if (err) // ...
});
또는
var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
Candy.create(array, function (err, jellybean, snickers) {
if (err) // ...
});
편집 : 많은 사람들이 언급했듯이 이것은 진정한 대량 삽입을 수행하지 않습니다. 단순히 save여러 번 호출하는 복잡성을 숨 깁니다 . 성능을 위해 대량 삽입을 달성하기 위해 실제 Mongo 드라이버를 사용하는 방법을 설명하는 답변과 의견이 아래에 있습니다.
Mongoose 4.4는 insertMany
문서 배열의 유효성을 검사하고 모두 유효한 경우 MongoDB에 삽입하는 바로 가기입니다. 이 함수는 .create ()보다 빠릅니다. 각 문서에 대해 하나의 작업이 아닌 서버에 하나의 작업 만 전송하기 때문입니다.
문제 # 723 에서 vkarpov15 인용 :
단점은 insertMany ()가 사전 저장 후크를 트리거하지 않지만 각 문서에 대해 1 번이 아닌 데이터베이스로 1 번만 왕복하므로 더 나은 성능을 가져야한다는 것입니다.
메서드의 서명은 다음과 동일합니다 create.
Model.insertMany([ ... ], (err, docs) => {
...
})
또는 약속 :
Model.insertMany([ ... ]).then((docs) => {
...
}).catch((err) => {
...
})
Mongoose에서 대량 삽입은 미들웨어에 액세스 할 필요가없는 한 .insert ()로 수행 할 수 있습니다.
Model.collection.insert(docs, options, callback)
https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js#L71-91
비동기 병렬을 사용하면 코드는 다음과 같습니다.
async.parallel([obj1.save, obj2.save, obj3.save], callback);
규칙은 Mongoose에서 비동기 (오류, 콜백)와 동일하기 때문에 자체 콜백으로 래핑 할 필요가 없습니다. 저장 호출을 배열에 추가하면 모든 작업이 완료되면 콜백을 받게됩니다.
mapLimit을 사용하면 병렬로 저장할 문서 수를 제어 할 수 있습니다. 이 예에서는 모든 항목이 성공적으로 저장 될 때까지 10 개의 문서를 병렬로 저장합니다.
async.mapLimit(myArray, 10, function(document, next){
document.save(next);
}, done);
나는 이것이 오래된 질문이라는 것을 알고 있지만 여기에 올바른 정답이 없다는 것이 걱정됩니다. 대부분의 답변은 모든 문서를 반복하고 각 문서를 개별적으로 저장하는 것에 대해 이야기합니다. 문서가 여러 개 있고 여러 요청 중 하나에 대해서도 프로세스가 반복되는 경우 나쁜 생각입니다.
MongoDB에는 특히 batchInsert()여러 문서를 삽입하기위한 호출이 있으며 이는 기본 mongodb 드라이버에서 사용해야합니다. Mongoose는이 드라이버를 기반으로하며 배치 삽입을 지원하지 않습니다. MongoDB를위한 객체 문서 모델링 도구로 간주되기 때문에 이치에 맞을 것입니다.
솔루션 : Mongoose는 기본 MongoDB 드라이버와 함께 제공됩니다. 이 드라이버를 요구하여 사용할 수 있습니다 require('mongoose/node_modules/mongodb')(잘 모르겠지만 작동하지 않는 경우 항상 mongodb npm을 다시 설치할 수 있지만 그래야한다고 생각합니다) 다음 적절한 작업을 수행합니다.batchInsert
최신 버전의 MongoDB는 대량 작업을 지원합니다.
var col = db.collection('people');
var batch = col.initializeUnorderedBulkOp();
batch.insert({name: "John"});
batch.insert({name: "Jane"});
batch.insert({name: "Jason"});
batch.insert({name: "Joanne"});
batch.execute(function(err, result) {
if (err) console.error(err);
console.log('Inserted ' + result.nInserted + ' row(s).');
}
추가 라이브러리를 사용하지 않는 또 다른 방법이 있습니다 (오류 검사 포함되지 않음).
function saveAll( callback ){
var count = 0;
docs.forEach(function(doc){
doc.save(function(err){
count++;
if( count == docs.length ){
callback();
}
});
});
}
당신은 몽구스에 의해 반환 약속을 사용할 수 있습니다 save, Promise모든이없는 몽구스에,하지만 당신은이 모듈에 기능을 추가 할 수 있습니다.
모두와 몽구스 약속을 강화하는 모듈을 만듭니다.
var Promise = require("mongoose").Promise;
Promise.all = function(promises) {
var mainPromise = new Promise();
if (promises.length == 0) {
mainPromise.resolve(null, promises);
}
var pending = 0;
promises.forEach(function(p, i) {
pending++;
p.then(function(val) {
promises[i] = val;
if (--pending === 0) {
mainPromise.resolve(null, promises);
}
}, function(err) {
mainPromise.reject(err);
});
});
return mainPromise;
}
module.exports = Promise;
그런 다음 몽구스와 함께 사용하십시오.
var Promise = require('./promise')
...
var tasks = [];
for (var i=0; i < docs.length; i++) {
tasks.push(docs[i].save());
}
Promise.all(tasks)
.then(function(results) {
console.log(results);
}, function (err) {
console.log(err);
})
insertMany많은 문서를 삽입하는 기능을 사용 합니다. 이것은 서버에 하나의 작업 만 보내고 Mongoosemongo 서버에 도달하기 전에 모든 문서의 유효성을 검사합니다. 기본적으로 Mongoose배열에있는 순서대로 항목을 삽입합니다. 주문을 유지하지 않아도 괜찮다면을 설정하십시오 ordered:false.
중요-오류 처리 :
때 ordered:true하나가 실패하면 검증 및 오류 처리가 그룹의 수단에서 일어나는 모든 일이 실패합니다.
때 ordered:false검증 및 오류 처리가 개별적으로 발생하고 작업이 계속됩니다. 오류는 오류 배열로 다시보고됩니다.
mongoHelper.js라는 파일을 추가하십시오.
var MongoClient = require('mongodb').MongoClient;
MongoClient.saveAny = function(data, collection, callback)
{
if(data instanceof Array)
{
saveRecords(data,collection, callback);
}
else
{
saveRecord(data,collection, callback);
}
}
function saveRecord(data, collection, callback)
{
collection.save
(
data,
{w:1},
function(err, result)
{
if(err)
throw new Error(err);
callback(result);
}
);
}
function saveRecords(data, collection, callback)
{
save
(
data,
collection,
callback
);
}
function save(data, collection, callback)
{
collection.save
(
data.pop(),
{w:1},
function(err, result)
{
if(err)
{
throw new Error(err);
}
if(data.length > 0)
save(data, collection, callback);
else
callback(result);
}
);
}
module.exports = MongoClient;
그런 다음 코드 변경에서
var MongoClient = require("./mongoHelper.js");
그런 다음 통화를 저장할 때 (컬렉션을 연결하고 검색 한 후)
MongoClient.saveAny(data, collection, function(){db.close();});
You can change the error handling to suit your needs, pass back the error in the callback etc.
This is an old question, but it came up first for me in google results when searching "mongoose insert array of documents".
There are two options model.create() [mongoose] and model.collection.insert() [mongodb] which you can use. View a more thorough discussion here of the pros/cons of each option:
Mongoose (mongodb) batch insert?
Here is an example of using MongoDB's Model.collection.insert() directly in Mongoose. Please note that if you don't have so many documents, say less than 100 documents, you don't need to use MongoDB's bulk operation (see this).
MongoDB also supports bulk insert through passing an array of documents to the db.collection.insert() method.
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
email : { type: String, index: { unique: true } },
name : String
});
var User = mongoose.model('User', userSchema);
function saveUsers(users) {
User.collection.insert(users, function callback(error, insertedDocs) {
// Here I use KrisKowal's Q (https://github.com/kriskowal/q) to return a promise,
// so that the caller of this function can act upon its success or failure
if (!error)
return Q.resolve(insertedDocs);
else
return Q.reject({ error: error });
});
}
var users = [{email: 'foo@bar.com', name: 'foo'}, {email: 'baz@bar.com', name: 'baz'}];
saveUsers(users).then(function() {
// handle success case here
})
.fail(function(error) {
// handle error case here
});
'Nice programing' 카테고리의 다른 글
| 이중 하이픈으로 시작하는 파일을 제거하는 방법은 무엇입니까? (0) | 2020.11.12 |
|---|---|
| Google 크롬에서 jsfiddle.net의 자바 스크립트 검사 (0) | 2020.11.12 |
| CMake가 C ++로 링커 언어를 결정할 수 없습니다. (0) | 2020.11.12 |
| Maven의 외부 라이브러리가있는 Android Studio에서 네임 스페이스 '앱'이 바인딩되지 않았습니다. (0) | 2020.11.12 |
| HH : MM : SS 형식의 시간을 초로 만 변환 하시겠습니까? (0) | 2020.11.12 |