Вставьте несколько записей и/или обновите определенные поля и верните только новые вставленные записи (MongoDB)

Привет, у меня есть следующая коллекция

var articles = [
                {
                  "title": "Article title1",
                  "content": "Article ... content......... 1. ",
                  "url": "http://matt.wordpress.com/article/X",
                  "last_fetched_time": new Date();
                },
                {
                  "title": "Article title2",
                  "content": "Article ... content......... 2. ",
                  "url": "http://matt.blogger.com/article/Y",
                  "last_fetched_time": new Date();
                }
            ];
db.collection('articles').insert(articles, {safe:true}, function(err, result) {}); //articles collection created

Я хочу периодически получать каналы блога из нескольких конечных точек параллельно, добавлять новые статьи в коллекцию и обновлять последнее выбранное поле даты и времени существующих статей в коллекции. Если я не прошу слишком многого, я также хочу, чтобы обратный вызов upsert возвращал только новые вставленные статьи.

//fetch articles periodically
fetchArticles = function(req, res) {
async.parallel([
    //fetch word press endpoint
        //get "title", "content", "url"
        //set last_fetched_time with new Date();

    //fetch blogger endpoint
        //get "title", "content", "url"
        //set last_fetched_time with new Date();
], 
function(err, results) {
    //merge results[0] and results[1] in a batch =[]
    //if the article url is not already in the collection, insert article into the articles collection
    //if the article url is found in the collection, update article because last_fetched_time changed 
    //finally return only new inserted articles, not updated ones
    db.collection('articles').update(batch, {safe:true, upsert : true}, function(err, result) { 

        //result = only new articles inserted
    });
});

}

поле URL должно быть уникальным, и я сделал

db.articles.ensureIndex({"url":1}, {unique: true, sparse:true, dropDups: true});

Проблема в том, что этот код не вставляет новые статьи


person user3211198    schedule 07.02.2014    source источник


Ответы (1)


Вы, кажется, перепутали свои функции, хотя я ясно вижу, что вы пытаетесь сделать.

Ваш batch, который вы передаете, содержит массив документов, которые вы хотите вставить/обновить. Проблема в том, что эта функция доступна только для вставьте метод.

Поскольку вы используете обновление параметр передачи массива документов для пакетной обработки недоступен. Обновления с установленным upsert, как вы сделали, предназначены для выпуска с первичными аргументами selector и одним «документом». Идея заключается в том, что там, где selector соответствует существующему документу, этот документ обновляется деталями в document. Если совпадение не найдено, вставляется новый документ.

Кроме того, поскольку вы не использовали, можно применить параметр несколько. Это делается для того, чтобы, когда selector соответствует более чем одному документу, изменения применялись ко всем соответствующим документам. Если не указано, поведение считается ложным, и будет обновлен только первый найденный соответствующий документ.

Может показаться, что хотя вы и хотите, чтобы это сопровождалось функциональностью пакетной обработки, в настоящее время ее не существует. Для этого есть JIRA, за которой вы можете следить/поддерживать.

https://jira.mongodb.org/browse/SERVER-2172

Обратитесь к ссылкам на функции в документации, где объясняются все доступные аргументы и параметры. Также см. документацию оболочки для подробного объяснения параметров:

http://docs.mongodb.org/manual/reference/method/db.collection.update/

person Neil Lunn    schedule 07.02.2014
comment
Спасибо, Нил, я только что попытался зациклить пакет и обновить каждую статью, но мне также нужно знать, была ли каждая статья обновлена ​​​​или вставлена ​​​​в первый раз. Но обратный вызов результата всегда возвращает 1 for (var i = batch.length - 1; i >= 0; i--) { articlesCollection.update({'last_fetched_time': batch[i].last_fetched_time}, batch[i], {safe:true, upsert : true}, function(err, result) { if(err) { console.log(err); return; } console.log(result); }); }; - person user3211198; 07.02.2014
comment
Есть опция «w», но я не могу понять, как ее использовать, и кажется, что опция «safe: true» недействительна для обновления, верно? - person user3211198; 07.02.2014
comment
Вот и напишите беспокойство. Найдите этот термин в документации. Все ссылки в ответе содержат достаточно документации для всех оставшихся вопросов. Количество обновленных и вставленных строк недоступно. - person Neil Lunn; 07.02.2014
comment
Таким образом, проблема записи, похоже, не возвращается, если запись была вставлена ​​​​или обновлена ​​​​информация, есть ли способ получить эту функциональность с помощью драйвера, такого как mangoose? - person user3211198; 07.02.2014