몽구스 (mongodb) 배치 삽입?


114

Mongoose v3.6 이상 은 이제 일괄 삽입을 지원 합니까 ? 몇 분 동안 검색했지만이 쿼리와 일치하는 항목은 몇 년 전이며 대답은 분명한 아니오였습니다.

편집하다:

나중에 참조 할 수 있도록 Model.create(). create()는 배열을 첫 번째 인수로 허용하므로 문서를 배열로 삽입 할 수 있습니다.

Model.create () 문서 참조


이전 질문에 대한 답변 을 참조하십시오 .
JohnnyHK 2013 년

감사. 그것이 내가 게시 한 후 찾은 결과입니다.
Geuis 2013 년

@Geuis는 귀하의 수정 사항을 답변으로 추가하고 수락하여 질문을 해결하십시오.
Filip Dupanović 2014 년


Model.create ()는 느리고 많은 수의 문서를 삽입하려는 경우 대신 이 방법을 사용하는 것이 좋습니다.
Lucio Paiva 2015 년

답변:


162

Model.create () 대 Model.collection.insert () : 더 빠른 접근 방식

Model.create()매우 큰 대량을 처리하는 경우 삽입을 수행하는 나쁜 방법입니다. 그것은 될 것입니다 매우 느립니다 . 이 경우 훨씬 더 나은Model.collection.insert 성능을 사용 하는 을 사용해야합니다 . 벌크의 크기에 따라 충돌도 발생합니다! 백만 개의 문서로 시도했지만 운이 없습니다. 사용 하는데 몇 초 밖에 걸리지 않았습니다.Model.create()Model.collection.insert

Model.collection.insert(docs, options, callback)
  • docs 삽입 할 문서의 배열입니다.
  • options선택적 구성 개체입니다- 문서 참조
  • callback(err, docs)모든 문서가 저장되거나 오류가 발생한 후에 호출됩니다. 성공시 docs는 지속되는 문서의 배열입니다.

Mongoose의 작성자가 여기 에서 지적했듯이이 방법은 모든 유효성 검사 절차를 우회하고 Mongo 드라이버에 직접 액세스합니다. 많은 양의 데이터를 처리하고 있기 때문에 트레이드 오프를해야합니다. 그렇지 않으면 데이터베이스에 데이터를 전혀 삽입 할 수 없습니다 (여기서는 수십만 개의 문서에 대해 이야기하고 있음을 기억하십시오).

간단한 예

var Potato = mongoose.model('Potato', PotatoSchema);

var potatoBag = [/* a humongous amount of potato objects */];

Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

업데이트 2019-06-22 : insert()여전히 잘 사용할 수 있지만 insertMany(). 매개 변수는 정확히 동일하므로 드롭 인 대체물로 사용할 수 있으며 모든 것이 잘 작동합니다 (반환 값은 약간 다르지만 어쨌든 사용하지 않을 것입니다).

참고



몽구스의 예를 들어주세요.
Steve K

15
Model.collectionMongo 드라이버를 직접 거치 므로 유효성 검사 및 후크를 포함한 모든 깔끔한 몽구스 항목을 잃게됩니다. 명심해야 할 사항입니다. Model.create후크를 잃지 만 여전히 유효성 검사를 거칩니다. 당신이 모든을 원하는 경우에, 당신은 반복해야합니다new MyModel()
부두 뤽 Gendreau에게

1
@ Pier-LucGendreau 당신은 절대적으로 옳지 만, 엄청난 양의 데이터를 다루기 시작하면 그것은 당신이해야하는 절충안입니다.
Lucio Paiva

1
새로운 독자에주의하십시오. "버전 2.6에서 변경 : insert ()는 작업 상태를 포함하는 객체를 반환합니다." 더 이상 문서가 없습니다.
Mark Ni

117

Mongoose 4.4.0은 이제 대량 삽입을 지원합니다.

Mongoose 4.4.0에는 모델 메서드를 사용하여 --true-- 대량 삽입이 도입되었습니다 .insertMany(). 루프를 사용 .create()하거나 배열을 제공하는 것 보다 훨씬 빠릅니다 .

용법:

var rawDocuments = [/* ... */];

Book.insertMany(rawDocuments)
    .then(function(mongooseDocuments) {
         /* ... */
    })
    .catch(function(err) {
        /* Error handling */
    });

또는

Book.insertMany(rawDocuments, function (err, mongooseDocuments) { /* Your callback function... */ });

다음에서 추적 할 수 있습니다.


2
현재이 방법은 옵션을 지원하지 않습니다.
Amri

답변 감사합니다. rawDocuments의 어떤 파싱이 제자리에 있어야하는지 아십니까? 나는 Json 객체의 배열로 시도해 보았고 삽입 된 것은 ID뿐입니다. :(
Ondrej Tokar

4
이것은 어떻게 bulkWrite다릅니 까? 여기를 참조하십시오 : stackoverflow.com/questions/38742475/...
드레이 Tokar

insertMany는 나를 위해 작동하지 않습니다. 나는 fatal error allocation failed. 하지만 collection.insert를 사용하면 완벽하게 작동합니다.
John

몽구스 스키마가 제공하는 추가 기능과 함께 작동합니까? 예를 들어 날짜가없는 경우 데이터를 추가합니다dateCreated : { type: Date, default: Date.now },
jack blank

22

실제로 Mongoose의 "만들기"메소드를 사용할 수 있습니다. 여기에는 문서 배열이 포함될 수 있습니다. 다음 예제를 참조하십시오.

Candy.create({ candy: 'jelly bean' }, { candy: 'snickers' }, function (err, jellybean, snickers) {
});

콜백 함수에는 삽입 된 문서가 포함됩니다. 얼마나 많은 항목을 삽입해야하는지 (위와 같이 고정 된 인수 길이) 알 수 없으므로 항목을 반복 할 수 있습니다.

var insertedDocs = [];
for (var i=1; i<arguments.length; ++i) {
    insertedDocs.push(arguments[i]);
}

업데이트 : 더 나은 솔루션

더 나은 솔루션은 Candy.collection.insert()대신 사용하는 것입니다 Candy.create()-위의 예에서 사용-더 빠르기 때문입니다 ( 각 항목을 create()호출 Model.save()하므로 더 느립니다).

자세한 내용은 Mongo 설명서를 참조하십시오. http://docs.mongodb.org/manual/reference/method/db.collection.insert/

( 이것을 지적한 arcseldon 에게 감사드립니다 )


groups.google.com/forum/#!topic/mongoose-orm/IkPmvcd0kds- 원하는 항목에 따라 링크에 더 나은 옵션이 있습니다.
arcseldon

{type:'jellybean'}대신에 의미 하지 {type:'jelly bean'}않습니까? Btw. 저것들은 어떤 이상한 유형입니까? Mongoose API의 일부입니까?
Steve K

2
type일반적으로 데이터베이스 개체의 ADT를 지정하기 위해 Mongoose에서 예약되어 있기 때문에 이름 지정 선택이 좋지 않습니다 .
Steve K

2
@sirbenbenji 나는 그것을 변경했지만 공식 문서에도 존재하는 예였습니다. 나는 이것을 위해 반대 투표를 할 필요가 없다고 생각합니다.
benske 2014 년

1
.collection 속성을 지정하면 Mongoose를 우회하는 것입니다 (유효성 검사, 'pre'메서드 ...)
Derek

4

배열에 값을 삽입하여 mongoDB 쉘을 사용하여 대량 삽입을 수행 할 수 있습니다.

db.collection.insert([{values},{values},{values},{values}]);

몽구스에 대량 삽입 방법이 있습니까?
SUNDARRAJAN K

1
YourModel.collection.insert()
Bill Dami 2014

.collection 속성을 해결함으로써 당신은 (... 검증, '사전'방법) 몽구스를 우회하는
데릭

이것은 몽구스가 아니며 원시 collection.insert답변 은이 답변 몇 주 전에 주어졌으며 훨씬 더 자세히 설명되었습니다.
Dan Dascalescu

4

mongoose를 사용하여 대량 삽입을 수행 할 수 있습니다. 그러나 예제는 작동하지 않으며 다음과 같아야합니다.

/* a humongous amount of potatos */
var potatoBag = [{name:'potato1'}, {name:'potato2'}];

var Potato = mongoose.model('Potato', PotatoSchema);
Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

대량 삽입에 스키마 인스턴스를 사용하지 마세요. 일반지도 객체를 사용해야합니다.


첫 번째 답변은 틀린 것이 아닙니다. 검증 만 있습니다
Luca Steeb

1
.collection 속성을 해결함으로써 당신은 (... 검증, '사전'방법) 몽구스를 우회하는
데릭

4

다음은 insertMany로 데이터를 저장하고 저장하는 두 가지 방법입니다.

1) 몽구스 insertMany는 대량 으로 문서 배열 저장

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const data = [/* array of object which data need to save in db */];

    Potato.insertMany(data)  
    .then((result) => {
            console.log("result ", result);
            res.status(200).json({'success': 'new documents added!', 'data': result});
    })
    .catch(err => {
            console.error("error ", err);
            res.status(400).json({err});
    });
})

2) 몽구스는 .save()

이 문서는 병렬로 저장됩니다.

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const saveData = []
    const data = [/* array of object which data need to save in db */];
    data.map((i) => {
        console.log(i)
        var potato = new Potato(data[i])
        potato.save()
        .then((result) => {
            console.log(result)
            saveData.push(result)
            if (saveData.length === data.length) {
                res.status(200).json({'success': 'new documents added!', 'data': saveData});
            }
        })
        .catch((err) => {
            console.error(err)
            res.status(500).json({err});
        })
    })
})

3

몽구스를 사용하면 1000 개 이상의 문서 제한이있는 것 같습니다.

Potato.collection.insert(potatoBag, onInsert);

당신이 사용할 수있는:

var bulk = Model.collection.initializeOrderedBulkOp();

async.each(users, function (user, callback) {
    bulk.insert(hash);
}, function (err) {
    var bulkStart = Date.now();
    bulk.execute(function(err, res){
        if (err) console.log (" gameResult.js > err " , err);
        console.log (" gameResult.js > BULK TIME  " , Date.now() - bulkStart );
        console.log (" gameResult.js > BULK INSERT " , res.nInserted)
      });
});

그러나 이것은 10000 개의 문서로 테스트 할 때 거의 두 배나 빠릅니다.

function fastInsert(arrOfResults) {
var startTime = Date.now();
    var count = 0;
    var c = Math.round( arrOfResults.length / 990);

    var fakeArr = [];
    fakeArr.length = c;
    var docsSaved = 0

    async.each(fakeArr, function (item, callback) {

            var sliced = arrOfResults.slice(count, count+999);
            sliced.length)
            count = count +999;
            if(sliced.length != 0 ){
                    GameResultModel.collection.insert(sliced, function (err, docs) {
                            docsSaved += docs.ops.length
                            callback();
                    });
            }else {
                    callback()
            }
    }, function (err) {
            console.log (" gameResult.js > BULK INSERT AMOUNT: ", arrOfResults.length, "docsSaved  " , docsSaved, " DIFF TIME:",Date.now() - startTime);
    });
}

1
.collection 속성을 해결함으로써 당신은 (... 검증, '사전'방법) 몽구스를 우회하는
데릭

0

프로젝트의 작업 및 관련 코드 공유 :

//documentsArray is the list of sampleCollection objects
sampleCollection.insertMany(documentsArray)  
    .then((res) => {
        console.log("insert sampleCollection result ", res);
    })
    .catch(err => {
        console.log("bulk insert sampleCollection error ", err);
    });

.insertMany솔루션은 이미 주어진 (및 설명)이 있었다 2,016 대답 .
Dan Dascalescu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.