在 Mongodb 更新及退回文件

我想得到更新的文档。这是我的原始代码,它成功地更新,但不返回文档。

collection.update({ "code": req.body.code },{$set:  req.body.updatedFields}, function(err, results) {
res.send({error: err, affected: results});
db.close();
});

我使用了 toArray函数,但是出现了这样的错误: “在没有提供回调的情况下不能使用 writeConcern”:

collection.update({ "code": req.body.code },{$set:  req.body.updatedFields}).toArray( function(err, results) {
res.send({error: err, affected: results});
db.close();
});

有什么想法吗?

91685 次浏览

Checkout the WriteResult object:

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

WriteResult result = collection.update({ "code": req.body.code },{$set:  req.body.updatedFields}, function(err, results) {
res.send({error: err, affected: results});
db.close();
});

result should have something like:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

If you want the updated results, do another query with the primary key.

collection.update() will only report the number of documents that were affected to its own callback.

To retrieve the documents while modifying, you can use collection.findOneAndUpdate() instead (formerly .findAndModify()).

collection.findOneAndUpdate(
{ "code": req.body.code },
{ $set: req.body.updatedFields },
{ returnOriginal: false },
function (err, documents) {
res.send({ error: err, affected: documents });
db.close();
}
);

The returnOriginal option (or new with Mongoose) lets you specify which version of a found document (original [default] or updated) is passed to the callback.

returnOriginal was deprecated in version 3.6. Use returnDocument: "before" | "after" for version 3.6 and later.


Disclaimer: This answer currently refers to the Node.js Driver as of version 3.6. As new versions are released, check their documentation for possibly new deprecation warnings and recommended alternatives.

Could not find any way to update many and return the modified records in docs, so I made a workaround.

At least one fault that I can find with below method is, you would not be able to tell if document is modified or already had the value that you are using:

function findAndUpdateMany(filter, updateOptions) {
return collection.find(filter).project({_id: 1}).toArray()
.then(function(matchingIds) {
filter = {_id: {$in: matchingIds}}
return collection.updateMany(filter, updateOptions)
}).then(function() {
return collection.find(filter).toArray()
})
}

The solution is to set: {returnOriginal: false}.

collection.findOneAndUpdate(
whereObj,
updateObj,
{returnOriginal: false});

In case you are using mongoose, returnOriginal: false did NOT work for me at v5.11.10,

but new: true worked,

from official mongoose docs:

const filter = { name: 'Jean-Luc Picard' };
const update = { age: 59 };


let doc = await Character.findOneAndUpdate(filter, update, {
new: true
});
doc.name; // 'Jean-Luc Picard'
doc.age; // 59

to get the updated doc when performing an update operation on one doc, use findOneAndUpdate() and in the options object, set returnDocument property to 'after'

let options = {returnDocument: 'after'}

const upadatedDoc = collection.findOneAndUpdate({'your query'},{'your update'}, options)

A bit late for the party but here's a simple 2022 solution to your question. I'm using NestJS for this app

const updatedPainting: Partial<IGallery> = {
imageAltTxt: updateGalleryDto.imageAltTxt,
name: updateGalleryDto.name,
dateCreated: updateGalleryDto.dateCreated,
size: updateGalleryDto.size,
description: updateGalleryDto.description,
isFeatured: updateGalleryDto.isFeatured || false,
};
return await this.galleryModel.findOneAndUpdate(
{ _id },
{ $set: { imageUrl, ...updatedPainting } },
{ returnDocument: 'after' },
);