Мангузова (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.