Mongoose (mongodb) toplu ek?


114

Mu Gelincik v3.6 + şimdi destek toplu ekler? Birkaç dakika aradım ama bu sorguyla eşleşen herhangi bir şey birkaç yaşında ve cevap kesin bir hayırdı.

Düzenle:

İleride başvurmak için cevap kullanmaktır Model.create(). create()bir diziyi ilk argüman olarak kabul eder, böylece belgelerinizi bir dizi olarak eklenecek şekilde geçirebilirsiniz.

Model.create () belgelerine bakın


Önceki soruya verilen bu cevabı görün .
JohnnyHK

Teşekkürler. Gönderdikten sonra bulduğum şey buydu.
Geuis

@Geuis, lütfen düzenlemenizi yanıt olarak ekleyin ve sorunuzu çözmek için kabul edin.
Filip Dupanović


Model.create () yavaştır ve çok sayıda belge eklemeyi düşünüyorsanız, bunun yerine bu yaklaşımı kullanmak daha iyidir .
Lucio Paiva

Yanıtlar:


162

Model.create () - Model.collection.insert (): daha hızlı bir yaklaşım

Model.create()çok büyük bir yığınla uğraşıyorsanız kesici uç yapmanın kötü bir yoludur. Çok yavaş olacak . Bu durumda Model.collection.insert, çok daha iyi performans gösteren kullanmalısınız . Yığın boyutuna bağlı olarak, Model.create()hatta çökecek! Milyonlarca belgeyle denendi, şans yok. Kullanmak Model.collection.insertsadece birkaç saniye sürdü.

Model.collection.insert(docs, options, callback)
  • docs eklenecek belge dizisidir;
  • optionsisteğe bağlı bir yapılandırma nesnesidir - belgelere bakın
  • callback(err, docs)tüm belgeler kaydedildikten veya bir hata meydana geldikten sonra çağrılacaktır. Başarı durumunda, belgeler kalıcı belgeler dizisidir.

Mongoose'un yazarının burada belirttiği gibi , bu yöntem herhangi bir doğrulama prosedürünü atlayacak ve Mongo sürücüsüne doğrudan erişecek. Bu, büyük miktarda veriyi işlediğiniz için yapmanız gereken bir değiş tokuş, aksi takdirde veri tabanınıza hiç ekleyemezsiniz (burada yüz binlerce belgeden bahsettiğimizi unutmayın).

Basit bir örnek

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 Güncellemesi : insert()yine de gayet iyi kullanılabilmesine rağmen , lehine kullanımdan kaldırıldı insertMany(). Parametreler tamamen aynıdır, bu yüzden onu bir drop-in değiştirme olarak kullanabilirsiniz ve her şey yolunda gitmelidir (iyi, dönüş değeri biraz farklıdır, ancak muhtemelen yine de kullanmıyorsunuz).

Referans



Lütfen Mongoose ile örnek veriniz.
Steve K

15
Yana Model.collectionMongo sürücüsü aracılığıyla doğrudan gider size doğrulama ve kancalar dahil tüm düzgün firavunfaresi şeyler kaybederler. Sadece akılda tutulması gereken bir şey. Model.createkancaları kaybeder, ancak yine de doğrulamadan geçer. Hepsini istiyorsanız, yinelemelisiniz venew MyModel()
Pier-Luc Gendreau

1
@ Pier-LucGendreau Kesinlikle haklısınız, ancak devasa miktarda veriyle uğraşmaya başladığınızda yapmanız gereken bir değiş tokuş.
Lucio Paiva

1
Yeni okuyuculara dikkat edin: "2.6 sürümünde değişti: insert (), işlemin durumunu içeren bir nesne döndürür". Artık belge yok.
Mark Ni

117

Mongoose 4.4.0 artık toplu eklemeyi destekliyor

Mongoose 4.4.0, model yöntemiyle --true-- toplu ekleme özelliğini sunar .insertMany(). Döngü yapmaktan .create()veya ona bir dizi sağlamaktan çok daha hızlıdır .

Kullanımı:

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

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

Veya

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

Takip edebilirsiniz:


2
Şu anda bu yöntem seçenekleri desteklemiyor.
Amri

Cevap için teşekkür ederim. RawDocuments'in hangi ayrıştırılması gerektiğine dair bir fikriniz var mı? Bunu bir dizi Json nesnesiyle denedim ve eklediği tek şey sadece kimlikleriydi. :(
Ondrej Tokar

4
Bu nasıl farklıdır bulkWrite? Buraya bakın: stackoverflow.com/questions/38742475/…
Ondrej Tokar

insertMany benim için çalışmıyor. Bir fatal error allocation failed. Ama collection.insert kullanırsam mükemmel çalışıyor.
John

Bu, firavun faresi şemasının sağladığı ekstra şeylerle çalışır mı? ex, tarih yoksa verileri eklerdateCreated : { type: Date, default: Date.now },
jack blank

22

Aslında, Mongoose'un "create" yöntemini kullanabilirsiniz, bir dizi belge içerebilir, şu örneğe bakın:

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

Geri arama işlevi eklenen belgeleri içerir. Kaç öğenin eklenmesi gerektiğini her zaman bilemezsiniz (yukarıdaki gibi sabit argüman uzunluğu), böylece bunlardan geçebilirsiniz:

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

Güncelleme: Daha iyi bir çözüm

Daha hızlı olduğu için - yukarıdaki örnekte kullanılan - Candy.collection.insert()yerine kullanmak daha iyi bir çözüm olacaktır Candy.create()( her bir öğeyi create()çağırmak Model.save(), böylece daha yavaştır).

Daha fazla bilgi için Mongo belgelerine bakın: http://docs.mongodb.org/manual/reference/method/db.collection.insert/

(bunu işaret ettiği için arcseldon'a teşekkürler )


groups.google.com/forum/#!topic/mongoose-orm/IkPmvcd0kds - Ne istediğinize bağlı olarak, bağlantının daha iyi bir seçeneği vardır.
arcseldon

Bunun {type:'jellybean'}yerine mi demek istiyorsun {type:'jelly bean'}? Btw. bunlar hangi türler? Mongoose API'nin bir parçası mı?
Steve K

2
Bu kötü bir adlandırma seçimi, çünkü typeMongoose'da genellikle bir veritabanı nesnesinin ADT'sini belirtmek için ayrılmıştır.
Steve K

2
@sirbenbenji Değiştirdim, ancak resmi belgelerde de bulunan bir örnek oldu. Bunun için olumsuz oy kullanmanın gerekmediğini düşünüyorum.
benske

1
.Collection özelliğini adresleyerek Mongoose'u (doğrulama, 'ön' yöntemler ...) atlıyorsunuz
Derek

4

Değerleri bir diziye ekleyerek mongoDB kabuğunu kullanarak toplu ekleme gerçekleştirebilirsiniz.

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

firavun faresinde toplu ekleme için bir yol var mı?
SUNDARRAJAN K

1
YourModel.collection.insert()
Bill Dami

.Collection özelliğini adresleyerek Mongoose'u atlıyorsunuz (doğrulama, 'pre' yöntemler ...)
Derek

Bu firavun faresi değildir ve ham collection.insertcevap bu cevaptan birkaç hafta önce verilmiş ve çok daha detaylı olarak açıklanmıştır.
Dan Dascalescu

4

En yüksek puanlı cevap olarak firavun faresini kullanarak toplu giriş yapabilirsiniz. Ancak örnek işe yaramaz, şöyle olmalıdır:

/* 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);
    }
}

Toplu ekleme için şema örneği kullanmayın, düz bir harita nesnesi kullanmalısınız.


İlk cevap yanlış değil, sadece doğrulandı
Luca Steeb

1
.Collection özelliğini adresleyerek Mongoose'u (doğrulama, 'ön' yöntemler ...) atlıyorsunuz
Derek

4

Burada insertMany ile veri kaydetmenin ve kaydetmenin iki yolu vardır

1) Mongoose, belge dizisini insertManytoplu olarak kaydedin

/* 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) Mongoose, belge dizisini kaydetme .save()

Bu belgeler paralel olarak kaydedilecektir.

/* 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

Firavun faresi kullanıldığında, 1000'den fazla belge sınırı olduğu görülüyor.

Potato.collection.insert(potatoBag, onInsert);

Kullanabilirsiniz:

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)
      });
});

Ancak bu, 10000 belgeyle test edildiğinde neredeyse iki kat daha hızlıdır:

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 özelliğini adresleyerek Mongoose'u atlıyorsunuz (doğrulama, 'pre' yöntemler ...)
Derek

0

Projemizden çalışan ve ilgili kodu paylaşmak:

//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Çözelti zaten verilmiş (ve açıklanmıştır) bu oldu 2016 cevap .
Dan Dascalescu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.