Мангузова (mongodb) пакетна вставка?


114

Чи тепер Mongoose v3.6 + підтримує пакетні вставки? Я шукав кілька хвилин, але все, що відповідає цьому запиту, - це пару років, і відповідь була однозначною ні.

Редагувати:

Для подальшого ознайомлення відповідь - використовувати Model.create(). create()приймає масив як свій перший аргумент, тому ви можете передавати свої документи, які потрібно вставити як масив.

Див. Документацію Model.create ()


Дивіться цю відповідь на попереднє запитання.
— JohnnyHK

Дякую. Ось що я нарешті знайшов після публікації.
— Гейс

@Geuis, будь ласка, додайте свою редагування як відповідь та прийміть її, щоб вирішити своє питання.
— Філіп Дупанович


Model.create () повільний, і якщо ви думаєте вставити величезну кількість документів, краще скористатися таким підходом .
— Lucio Paiva

Відповіді:


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)буде викликано після збереження всіх документів або виникнення помилки. На успіх, Документи - це масив збережених документів.

Як автор Mongoose вказується, тут , це буде метод обходу будь-яких процедур перевірки і доступу водія Монго безпосередньо. Це ви можете зробити, оскільки ви обробляєте велику кількість даних, інакше ви взагалі не зможете вставити їх у свою базу даних (пам’ятайте, що ми говоримо тут про сотні тисяч документів).

Простий приклад

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(). Параметри точно такі самі, тож ви можете просто використовувати його як замінник, що випадає, і все повинно працювати нормально (ну, значення повернення дещо інше, але ви, мабуть, не використовуєте його все одно).

Довідково


1
groups.google.com/forum/#!topic/mongoose-orm/IkPmvcd0kds Каже, що це все насправді.
— arcseldon

Наведіть приклад з Мангустом.
— Стів К

15
Оскільки Model.collectionпроходить безпосередньо через драйвера Mongo, ви втрачаєте всі акуратні речі з мангуста, включаючи перевірку та гачки. Просто щось пам’ятати. Model.createвтрачає гачки, але все ж проходить перевірку. Якщо ви хочете все це, ви повинні повторити іnew MyModel()
— Pier-Luc Gendreau

1
@ Pier-LucGendreau Ви абсолютно праві, але це компроміс, який ви повинні зробити, як тільки ви почнете мати справу з гумористичним обсягом даних.
— Лусіо Пайва

1
Будьте уважні до нових читачів: "Змінено у версії 2.6: insert () повертає об'єкт, що містить статус операції". Більше немає документів.
— Марк Нік

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
Наразі цей метод не підтримує варіанти.
— Амрі

Дякую за відповідь. Будь-яка ідея, який повинен бути синтаксичний аналіз сирих Документів? Я спробував це з масивом об’єктів Json, і все, що він вставив, - це лише їх ідентифікатори. :(
— Ондрей Токар

4
Чим це відрізняється bulkWrite? Дивіться тут: stackoverflow.com/questions/38742475/…
— Ондрей Токар

insertMany не працює для мене. Я отримав fatal error allocation failed. Але якщо я використовую collection.insert, вона прекрасно працює.
— Іван

Чи буде це працювати з додатковими матеріалами, які надає схема мангуста? коли це додасть дані, якщо немає датиdateCreated : { type: Date, default: Date.now },
— джек пустий

22

Дійсно, ви можете використовувати метод "create" Мангуста, він може містити масив документів, дивіться цей приклад:

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?
— Стів К

2
Ну, це поганий вибір імен, оскільки typeзазвичай в Мангузі зарезервовано для позначення ADT об'єкта бази даних.
— Стів К

2
@sirbenbenji Я змінив це, але це був приклад також в офіційній документації. Думаю, не потрібно було це робити, я думаю.
— benske

1
Звертаючись до властивості .collection, ви обходите мангусту (валідація, «попередні» методи ...)
— Дерек

4

Ви можете виконати об'ємну вставку за допомогою оболонки mongoDB, використовуючи вставлення значень у масив.

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

чи є спосіб у мангуста для об'ємної вставки?
— SUNDARRAJAN K

1
YourModel.collection.insert()
— Білл Дамі

Звертаючись до властивості .collection, ви обходите "Мангусту" (валідація, "попередні методи ..."
— Дерек

Це не мангуст, і груба collection.insertвідповідь була дана за кілька тижнів до цієї відповіді, і пояснена набагато детальніше.
— Дан Даскалеску

4

Ви можете виконати об'ємну вставку, використовуючи мангусту, як найкращу відповідь. Але приклад не може працювати, він повинен бути:

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

Не використовуйте екземпляр схеми для масової вставки, ви повинні використовувати звичайний об’єкт карти.


Перша відповідь не є помилковою, вона просто підтверджує
— Лука Стіб

1
Звертаючись до властивості .collection, ви обходите "Мангусту" (валідація, "попередні" методи ...)
— Дерек

4

Ось обидва способи збереження даних за допомогою вставкиMany та збереження

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Рішення вже було дано (і пояснили) в цьому 2016 році відповідь .
— Дан Даскалеску
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.