Как проверить, был ли $addToSet Mongo дубликатом или нет

Я использую Mongoskin + NodeJS для добавления новых ключевых слов в MongoDB. Я хочу уведомить пользователя о том, что запись была дубликатом, но не знаю, как это сделать.

/*
* POST to addkeyword.
*/
router.post('/addkeyword', function(req, res) {
var db = req.db;
db.collection('users').update({email:"[email protected]"}, {'$addToSet': req.body }, function(err, result) {
    if (err) throw err;
    if (!err) console.log('addToSet Keyword.' );
}); 
});

Результат, похоже, бесполезен, поскольку в нем не указано, было ли добавлено ключевое слово или нет.


person davegallant    schedule 08.05.2014    source источник


Ответы (3)


По крайней мере, в оболочке вы можете различить, был ли документ изменен или нет (см. nModified).

> db.test4.update({_id:2}, {$addToSet: {tags: "xyz" }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.test4.update({_id:2}, {$addToSet: {tags: "xyz" }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

Обновление узла

Когда вы используете collection.update(criteria, update[[, options], callback]);, вы можете получить количество записей, которые были изменены.

Из узла документы

обратный вызов — это обратный вызов, который выполняется после обновления записей. Имеет два параметра, первый — объект ошибки (если произошла ошибка), второй — количество записей, которые были изменены.

Еще одно обновление

Кажется, по крайней мере, в версии 1.4.3 собственный драйвер Mongo Node ведет себя не так, как задокументировано. Можно обойти это, используя массовый API (представленный в Mongo 2.6):

var col = db.collection('test');
// Initialize the Ordered Batch
var batch = col.initializeOrderedBulkOp();
batch.find({a: 2}).upsert().updateOne({"$addToSet": {"tags": "newTag"}});
// Execute the operations
batch.execute(function(err, result) {
  if (err) throw err;
  console.log("nUpserted: ", result.nUpserted); 
  console.log("nInserted: ", result.nInserted); 
  console.log("nModified: ", result.nModified); // <- will tell if a value was added or not
  db.close();
});
person Sebastian    schedule 08.05.2014
comment
Приятно отметить, что это новая функция, до версии 2.6 она записывала изменения, даже если это не так. - person Sammaye; 08.05.2014
comment
Вы уверены, что это работает так, как описано для MongoDb 2.6? Я только что попробовал, и он вернул 1 в обратном вызове для этого случая. Таким образом, кажется, что он возвращает количество совпадений, но не измененное количество. Я использую MongoDB 2.6.0 в Windows. - person Andrei Beziazychnyi; 08.05.2014
comment
@AndreiBeziazychnyi Вы используете последнюю версию драйвера? Скорее всего, изменение w API также потребовало изменения драйвера. - person Sammaye; 09.05.2014
comment
Я обновил драйвер перед проверкой, последняя версия 1.4.3. Не могли бы вы подтвердить, что описанный метод работает для вас в node.js? - person Andrei Beziazychnyi; 09.05.2014

Вы можете использовать db.users.findAndModify({email:"[email protected]"},[],{'$addToSet': { bodies: req.body }},{'new':false}). Обратите внимание на переключатель new:false, он позволяет получить документ перед обновлением, и вы можете проверить, содержит ли массив элемент перед обновлением. Однако это может быть проблематичным подходом, если ваши документы большие, потому что вы анализируете их на стороне клиента.

P.S. Ваш исходный запрос с $addToSet неверен: имя поля отсутствует.

Изменить: я пытался использовать счетчик, возвращаемый update, но он возвращает 1 во всех случаях. Вот код, который я использовал для тестирования с MongoDB 2.6:

var MongoClient = require('mongodb').MongoClient;

MongoClient.connect('mongodb://localhost:27017/mtest', function(err, db) {
   if(err) throw err;

   db.collection('test').insert({_id:1,bodies:["test"]},function(err,item){

     db.collection('test').update({_id:1},{$addToSet:{bodies:"test"}}, function(err,affected){
        if(err) throw err;
        console.log(affected); //1 in console

    });
 });

});
person Andrei Beziazychnyi    schedule 08.05.2014

я обновляю массив из коллекции с помощью этого JSON:

{
    "<arrayname>":"<value>"
}

маршрут.js

routes.post("/api/:id", Controller.addOne);

Контроллер.js

async addOne(req, res) {
    //juryman id to list add
    if (Object.keys(req.body).length === 1) {
      console.log("Size 1");
    }
    await Session.findOneAndUpdate(
      { _id: req.params.id },
      { $addToSet: req.body }
    )
      .then(function(success) {
        res.send("Successfully saved.");
      })
      .catch(function(error) {
        res.status(404).send(error);
      });
  },

У меня есть пять массивов в моей коллекции, и это изменяет значение имени массива JSON и правильно обновляет соответствующий массив коллекции. Это работает только для одного элемента.

person BENEVID FELIX DA SILVA    schedule 27.02.2020