Menyisipkan luwak (mongodb)?

114

Apakah Mongoose v3.6 + mendukung penyisipan batch sekarang? Saya telah mencari selama beberapa menit tetapi apa pun yang cocok dengan kueri ini berumur beberapa tahun dan jawabannya jelas tidak.

Edit:

Untuk referensi di masa mendatang, jawabannya adalah dengan menggunakan Model.create(). create()menerima larik sebagai argumen pertamanya, jadi Anda bisa meneruskan dokumen Anda untuk disisipkan sebagai larik.

Lihat dokumentasi Model.create ()

Geuis
sumber
Lihat jawaban ini untuk pertanyaan sebelumnya.
JohnnyHK
Terima kasih. Itulah yang akhirnya saya temukan setelah memposting.
Geuis
@Geuis tolong tambahkan hasil edit Anda sebagai jawaban dan terima untuk menjawab pertanyaan Anda.
Filip Dupanović
Model.create () lambat dan jika Anda mempertimbangkan untuk memasukkan dokumen dalam jumlah besar, lebih baik menggunakan pendekatan ini .
Lucio Paiva

Jawaban:

162

Model.create () vs Model.collection.insert (): pendekatan yang lebih cepat

Model.create()adalah cara yang buruk untuk melakukan penyisipan jika Anda berurusan dengan massal yang sangat besar. Ini akan sangat lambat . Dalam hal ini Anda harus menggunakan Model.collection.insert, yang kinerjanya jauh lebih baik . Bergantung pada ukuran massal, Model.create()bahkan akan crash! Mencoba dengan sejuta dokumen, tidak berhasil. Menggunakannya Model.collection.inserthanya butuh beberapa detik.

Model.collection.insert(docs, options, callback)
  • docs adalah larik dokumen yang akan disisipkan;
  • optionsadalah objek konfigurasi opsional - lihat dokumen
  • callback(err, docs)akan dipanggil setelah semua dokumen disimpan atau terjadi kesalahan. Jika berhasil, dokumen adalah kumpulan dokumen yang ada.

Seperti yang ditunjukkan oleh penulis Mongoose di sini , metode ini akan melewati semua prosedur validasi dan mengakses driver Mongo secara langsung. Ini adalah trade-off yang harus Anda lakukan karena Anda menangani data dalam jumlah besar, jika tidak, Anda tidak akan dapat memasukkannya ke database Anda sama sekali (ingat, kita membicarakan ratusan ribu dokumen di sini).

Contoh sederhana

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

Perbarui 2019-06-22 : meskipun insert()masih dapat digunakan dengan baik, itu sudah usang dan mendukung insertMany(). Parameternya persis sama, jadi Anda bisa menggunakannya sebagai pengganti drop-in dan semuanya akan berfungsi dengan baik (yah, nilai kembaliannya sedikit berbeda, tetapi Anda mungkin tidak menggunakannya).

Referensi

Lucio Paiva
sumber
1
groups.google.com/forum/#!topic/mongoose-orm/IkPmvcd0kds Benar-benar mengatakan semuanya.
arcseldon
Tolong beri contoh dengan Mongoose.
Steve K
15
Karena Model.collectionlangsung melewati driver Mongo, Anda kehilangan semua barang luwak yang rapi termasuk validasi dan kait. Hanya sesuatu yang perlu diingat. Model.createkehilangan pengait, tetapi masih melalui validasi. Jika Anda menginginkan semuanya, Anda harus mengulang dannew MyModel()
Pier-Luc Gendreau
1
@ Pier-LucGendreau Anda benar, tetapi ini adalah pengorbanan yang harus Anda lakukan setelah Anda mulai berurusan dengan sejumlah besar data.
Lucio Paiva
1
Hati-hati dengan pembaca baru: "Berubah pada versi 2.6: Insert () mengembalikan objek yang berisi status operasi". Tidak ada lagi dokumen.
Mark Ni
117

Mongoose 4.4.0 sekarang mendukung penyisipan massal

Mongoose 4.4.0 memperkenalkan --true-- penyisipan massal dengan metode model .insertMany(). Ini jauh lebih cepat daripada mengulang .create()atau menyediakannya dengan array.

Pemakaian:

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

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

Atau

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

Anda dapat melacaknya di:

Derek
sumber
2
Saat ini, metode ini tidak mendukung opsi.
Amri
Terima kasih atas jawabannya. Adakah ide penguraian rawDocuments apa yang harus dilakukan? Saya sudah mencobanya dengan berbagai objek Json dan semua yang dimasukkan hanyalah ID mereka. :(
Ondrej Tokar
4
Bagaimana ini berbeda dengan bulkWrite? Lihat di sini: stackoverflow.com/questions/38742475/…
Ondrej Tokar
insertMany tidak bekerja untuk saya. Saya punya fatal error allocation failed. Tetapi jika saya menggunakan collection.insert, itu berfungsi dengan sempurna.
Yohanes
Apakah ini akan berfungsi dengan hal-hal tambahan yang disediakan skema luwak? ex ini akan menambahkan data jika tidak ada tanggaldateCreated : { type: Date, default: Date.now },
jack kosong
22

Memang, Anda dapat menggunakan metode "create" dari Mongoose, ini dapat berisi berbagai dokumen, lihat contoh ini:

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

Fungsi panggilan balik berisi dokumen yang disisipkan. Anda tidak selalu tahu berapa banyak item yang harus dimasukkan (argumen tetap panjang seperti di atas) sehingga Anda dapat mengulanginya:

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

Pembaruan: Solusi yang lebih baik

Solusi yang lebih baik akan digunakan Candy.collection.insert()daripada Candy.create()- digunakan dalam contoh di atas - karena lebih cepat ( create()memanggil Model.save()setiap item jadi lebih lambat).

Lihat dokumentasi Mongo untuk informasi lebih lanjut: http://docs.mongodb.org/manual/reference/method/db.collection.insert/

(terima kasih kepada arcseldon karena menunjukkan hal ini)

benske
sumber
groups.google.com/forum/#!topic/mongoose-orm/IkPmvcd0kds - Bergantung pada apa yang Anda inginkan, tautan memiliki opsi yang lebih baik.
arcseldon
Bukankah maksudmu {type:'jellybean'}bukan {type:'jelly bean'}? Btw. tipe aneh apa itu? Apakah mereka bagian dari Mongoose API?
Steve K
2
Nah, itu pilihan penamaan yang buruk, karena typebiasanya disediakan dalam bahasa Mongoose untuk denominasi ADT dari objek database.
Steve K
2
@sirbenbenji Saya mengubahnya, tetapi itu adalah contoh yang juga ada di dokumentasi resmi. Saya pikir tidak perlu memberi suara negatif untuk ini.
benske
1
Dengan menangani properti .collection Anda melewati Mongoose (validasi, metode 'pre' ...)
Derek
4

Anda dapat melakukan penyisipan massal menggunakan mongoDB shell menggunakan memasukkan nilai-nilai dalam array.

db.collection.insert([{values},{values},{values},{values}]);
SUNDARRAJAN K
sumber
apakah ada cara di luwak untuk memasukkan massal?
SUNDARRAJAN K
1
YourModel.collection.insert()
Bill Dami
Dengan menangani properti .collection Anda melewati Mongoose (validasi, metode 'pre' ...)
Derek
Ini bukan luwak, dan collection.insertjawaban mentah diberikan beberapa minggu sebelum jawaban ini, dan dijelaskan dengan lebih rinci.
Dan Dascalescu
4

Anda dapat melakukan penyisipan massal menggunakan luwak, sebagai jawaban skor tertinggi. Tetapi contoh tidak dapat bekerja, seharusnya:

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

Jangan gunakan contoh skema untuk penyisipan massal, Anda harus menggunakan objek peta biasa.

pengguna2582680
sumber
Jawaban pertama tidak salah, hanya memiliki validasi
Luca Steeb
1
Dengan menangani properti .collection Anda melewati Mongoose (validasi, metode 'pre' ...)
Derek
4

Berikut adalah kedua cara menyimpan data dengan insertMany dan save

1) Mongoose menyimpan berbagai dokumen insertManysecara massal

/* 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 menyimpan berbagai dokumen dengan .save()

Dokumen-dokumen ini akan menyimpan paralel.

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

Tampaknya menggunakan luwak ada batasan lebih dari 1000 dokumen, saat menggunakan

Potato.collection.insert(potatoBag, onInsert);

Kamu bisa memakai:

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

Tetapi ini hampir dua kali lebih cepat saat menguji dengan 10.000 dokumen:

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);
    });
}
ddennis
sumber
1
Dengan menangani properti .collection Anda melewati Mongoose (validasi, metode 'pre' ...)
Derek
0

Berbagi kode yang berfungsi dan relevan dari proyek kami:

//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);
    });
Zameer
sumber
The .insertManysolusi sudah diberikan (dan menjelaskan) dalam 2016 jawabannya .
Dan Dascalescu