猫鼬 findOneAndUpdate Upsert _id null?
Posted
技术标签:
【中文标题】猫鼬 findOneAndUpdate Upsert _id null?【英文标题】:Mongoose findOneAndUpdate Upsert _id null? 【发布时间】:2013-06-19 02:57:39 【问题描述】:我想要一个方法来创建或更新政策文档。搜索和尝试不同的技术,如this one,我为我的文档想出了一个空 _id。使用 findByIdAndUpdate 也有类似的效果。
我看到集合中插入了一个文档,但 _id 字段为空:
exports.savePolicy = function (plcy, callback)
console.log('priority is : ' + plcy.priority)
try
var policy = new Policy(plcy);
var query = _id: plcy._id; //this may be null
var update =
name: plcy.name || defaults.policyDefaults.name,
longDescription: plcy.longDescription || defaults.policyDefaults.longDescription,
shortDescription: plcy.shortDescription || defaults.policyDefaults.shortDescription,
priority: plcy.priority, colorHex: plcy.colorHex || defaults.policyDefaults.colorHex,
settings: plcy.settings || [],
parentPolicyId: plcy.parentPolicyId || null
Policy.findOneAndUpdate(query, update, upsert: true, function (err, data)
callback(err, data);
);
catch (e)
log.error('Exception while trying to save policy: ' + e.message);
callback(e, null);
当 _id 不是更新时,有什么办法可以让 _id 不为空?
【问题讨论】:
你有没有想过这个问题?我遇到了同样的问题。我最终手动检查了 _id,然后调用 findOneAndUpdate 进行更新或调用 create() 获取新记录。 【参考方案1】:null
在 MongoDB 中是一个有效的 _id
值,因此如果您不希望在新文档中使用它,则必须确保将 null
值替换为 query
中的新 ObjectID
:
var query = _id: plcy._id;
if (!query._id)
query._id = new mongoose.mongo.ObjectID();
// the rest stays the same...
【讨论】:
我们使用 ObjectIds 来推断创建时间戳。在服务器端创建 ObjectId 而不是客户端创建它们不是最好的吗?【参考方案2】:我遇到了同样的问题,但无法找到让它工作的方法。我最终像这样编写了自己的 upsert 方法....
var upsert = function(model, data, f)
if (!data._id)
model.create(data, f);
else
var id = data._id;
delete data._id;
model.findOneAndUpdate(_id: id, data, f);
这让我可以用一行代码为我的任何模型调用它...
upsert(Team, team, f);
可能有更好的方法,但这对我有用。我可以进行更新和插入,但插入时不会得到空 _id。
【讨论】:
嗯,你可以使用类似的方法来解决这个问题:Model.findOneAndUpdate( _id: id || Mongoose.Types.ObjectId() , $set: attrs, upsert: true , 新: true )【参考方案3】:感谢 JohnnyHK 在上面提供的有用答案。我想出了一个单行,因为它被频繁使用:
query = args._id ? _id: args._id : _id: new ObjectId() ;
它依赖于以下要求:
const ObjectId = require('mongodb').ObjectID;
【讨论】:
【参考方案4】:我没有使用 Mongoose,但我遇到了与 MongoDB 类似的问题。对于插入新对象时的 Upsert 操作,MongoDB 将 null
设置为 _id
。
我在打电话:
findOneAndUpdate(my_id:'my_unique_id', obj, upsert: true)
其中obj._id
是undefined
。
问题是_id
出现在键列表Object.keys(obj)
上。我发现我分配了obj._id = some_variable
,其中some_variable
是undefined
,这导致_id
出现在键列表中。
我通过在 upsert 之前调用来应用解决方法:
if (_.isUndefined(obj._id))
delete obj._id;
【讨论】:
【参考方案5】:这可能很有用(来自the docs):
如果您在查询参数或替换文档中指定 _id 字段,MongoDB 会在插入的文档中使用该 _id 字段。
所以当你写的时候:
model.findOneAndUpdate(_id: id, data, f);
而id
是null
,它会插入一个以null
为id的文档。
【讨论】:
【参考方案6】:如果有 ID,则更新文档或在没有 ID 时创建新文档的最简单方法是:
Model.findOneAndUpdate( _id: id ?? new mongoose.Types.ObjectId() , updates, upsert: true );
注意nullish coalescing operator (??) 的使用,它允许 0 作为有效 id。 updates
对象不需要包含 id
属性,因为 mongoose 将 add it automatically:
如果没有文档匹配过滤器,MongoDB 将通过组合过滤器和更新插入一个,如下所示。
【讨论】:
【参考方案7】:由于我们现在可以在 javascript 中解构对象时添加默认属性,因此在检查文档是否存在的情况下,我发现这是通过现有 _id 查询或在同样的操作,避免了null id问题:
// someController.js 使用 POST 路由
async function someController(req, res)
try
const
// the default property will only be used if the _id doesn't exist
_id: new mongoose.Types.ObjectId(),
otherProp,
anotherProp
= req.body;
const createdOrUpdatedDoc = await SomeModel.findOneAndUpdate(
_id
,
otherProp,
anotherProp
,
new: true,
upsert: true
).exec();
return res.json(201).json(createdOrUpdatedDoc);
catch (error)
return res.json(400).send(
error,
message: "Could not do this"
)
【讨论】:
【参考方案8】:尝试将'new'参数设置为true:
upsert: true, new: true
更多信息:https://github.com/Automattic/mongoose/issues/2939
【讨论】:
【参考方案9】:尝试在更新调用中将 upsert 参数设置为 true。来自 mongoid 文档:http://docs.mongodb.org/manual/reference/method/db.collection.update/#update-parameter
可选。如果设置为 true,则在没有文档与查询条件匹配时创建一个新文档。默认值为false,没有找到匹配时不插入新文档。
【讨论】:
以上是关于猫鼬 findOneAndUpdate Upsert _id null?的主要内容,如果未能解决你的问题,请参考以下文章
猫鼬 findOneAndUpdate 和 runValidators 不工作
猫鼬 findOneAndUpdate 为 err 和 doc 返回 null(使用 Jest)
将 findOne 和 findOneAndUpdate 与 HTTP 请求一起使用(猫鼬)
猫鼬 findOneAndUpdate Upsert _id null?
猫鼬不是 $setting array.$.booleanValue 当我 findOneAndUpdate(paramOne: p, paramTwo, array.keyName: valueNa
猫鼬不是 $setting array.$.booleanValue 当我 findOneAndUpdate(paramOne: p, paramTwo, array.keyName: valueNa