Mongodb update $pull always return 1

冷暖自知 提交于 2019-12-11 08:45:48

问题


I want to delete an embedded object from an array, using this query. It works fine, but the result is always 1. No matter if an array element was pulled or not. This makes it hard to respond to the request in a proper way.

db.clients.update({_id: someId}, {$pull: {someArray: {id: req.params.id}}}, function(err, result) {
  if (err) return next(err);
  res.json(result);
});

Q) Is there a way to make this query return for example null or zero when an element is not pulled?


回答1:


While there have been some changes in MongoDB 2.6, the implementation used by most drivers is still the "legacy" write concern operations obtained from the slightly inappropriately named .getLastError() call.

It is a know issue here that as long as an update statement "matches" a document then the result obtained will be equal to the number of "matches" regardless if the operation actually modified the document. So operations such as $pull and $addToSet may not actually do anything to the document content where either the queried element by a "pull" did not exist, or already existed for an "addToSet".

There is the WriteResult which is available in the shell ( and in fact in all drivers now ) but here is where the confusion steps in. The .update() commands that are implemented in the driver and the shell are not in fact the same. In the shell, this method actually wraps the "Bulk Operations API" methods, and will try to use those methods when connected to a capable server and only fall back to the legacy implementation when the server is not capable.

For this reason, you presently need to either build the same kind of logic into your application or otherwise just live with that your application may never actually connect to a server node below a 2.6 version and use the Bulk API methods exclusively:

db.collection('testcol',function(err,col) {
  if (err) throw err;

  var bulk = col.initializeOrderedBulkOp();

  bulk.find({ "_id": someId}).updateOne({ 
      "$pull": { 
          "someArray": { "id": req.params.id }
       }
  });
  bulk.execute(function(err,result) {
    if (err) throw err;
    console.log( result.toJSON() );
  });
});

So that is really what is happening "under the hood" in the shell methods for modern MongoDB releases. The "Write Result" that is returned will accurately reflect both the number of documents matched and the "modified" number as well. So if nothing was actually changed the "modified" contains 0.

But you must use the methods directly. Unless someone else wants to do it at a higher level of API to provide the same kind of abstraction that the shell does right now, the original methods will not change in order to maintain backwards compatibility.




回答2:


Which mongo version are you using ?. For the version 2.6 the update return a WriteResult object with the status of the update operation, as you can see in the mongo documentarion



来源:https://stackoverflow.com/questions/26144405/mongodb-update-pull-always-return-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!