如果未找到 ID,则 Mongoose 更新文档或插入新文档(Express REST API)

Posted

技术标签:

【中文标题】如果未找到 ID,则 Mongoose 更新文档或插入新文档(Express REST API)【英文标题】:Mongoose Update Document or Insert New Document if ID Is Not Found (Express REST API) 【发布时间】:2017-11-27 11:12:05 【问题描述】:

我已经设置了一个 Express REST Api,并希望实现一个检查某个对象 ID 是否存在的任务。

如果 Mongo 数据库中存在该 ID,我想使用 Put 请求更新此文档。这部分已经在我的代码中工作了。

如果数据库中尚不存在该 ID,我想创建一个新文档。为此,我尝试将“upsert”选项设置为 true,但如果我现在向一个 ID 发出 put 请求,该 ID 不在我的数据库中,但它会返回错误:

throw er; // Unhandled 'error' event
  ^
CastError: Cast to ObjectId failed for value "34455ab67" at path "_id" for model "event"

这是我的事件模型代码:

var mongoose = require('mongoose');

var eventSchema = mongoose.Schema(
   name: 
       type: String,
       required: true
   
);
var Events = module.exports = mongoose.model('event', eventSchema, 'event');

module.exports.updateEvent = function (id, event, options, callback) 
   var query = _id : id;
   var update = 
       name: event.name,
   ;
   Events.findOneAndUpdate(query, update, options, callback);
;

这是 REST API 调用

app.put('/api/event/:_id', function(req, res)            
   var id = req.params._id;
   var event = req.body;
   var options = 
       upsert: true,
       new: true,
       setDefaultsOnInsert: true
   ;
   Events.updateEvent(id, event, options, function(err, event)
       if(err)
           trow err;
       
       res.json(event);
   )
);

任何帮助将不胜感激!

【问题讨论】:

您在参数中提供给id 的值对于转换为架构中_id 字段的ObjectId 类型无效,您将其作为您的查询提供陈述。因此,您要么使用不正确的值进行调用,要么实际上是要匹配 _id 字段以外的另一个属性。您的架构仅显示name 和隐含的_id,因此它可能只是一个不正确的值。您能显示您希望更新的实际数据库对象吗?另一个考虑是架构是错误的,需要为_id 定义一个String 【参考方案1】:

发生此错误是因为您定义了没有“_id”的事件架构,因此默认情况下“_id”属性的类型变为“ObjectId”,然后当您尝试使用此值“34455ab67”发送“_id”时,猫鼬方法尝试了将其转换为“ObjectId”类型,但它是无效的字符串。所以你应该做以下事情:

    为“_id”属性发送有效的字符串值。 在将输入字符串转换为“ObjectId”之前验证输入字符串。 如果输入字符串有效,将其转换为“ObjectId”,然后在 mongoose 查询。

检查以下示例:

var mongoose = require('mongoose');
//inputId is the input string passed from the front end
if (inputId.match(/^[0-9a-fA-F]24$/)) 
  // it's a valid string to be converted to "ObjectId"
  var id = mongoose.Types.ObjectId(inputId);
  //then use this id in your mongoose queries.
 else 
  //Not valid     

或者您可以使用“String”类型定义“_id”以简化此过程,但这取决于您的需要。

【讨论】:

该错误实际上发生了,因为 mongoose 已经在尝试“自动转换”到 ObjectId,因为这是为提供参数的属性定义的类型。因此,错误的真正原因是输入“字符串”甚至不是要转换为ObjectId 的有效数据,正如错误消息中所证明的那样。因此,尝试强制转换的“显式”只会导致相同的错误,因此不能解决这里的问题。 另一点,我们可以使用简单的正则表达式来验证输入字符串,而不是使用“ObjectId.isValid”,因为如果找到它也接受与 ObjectId 格式不匹配的字符串值!我会用这些更新来更新我的答案,以便更清楚 在模式中将 _id 定义为字符串并覆盖对象 id 后,它起作用了。非常感谢

以上是关于如果未找到 ID,则 Mongoose 更新文档或插入新文档(Express REST API)的主要内容,如果未能解决你的问题,请参考以下文章

如果未找到值,则使用 mongoose 将对象添加到数组中,否则更新字段

Mongoose 更新或插入许多文档

Mongoose:过滤,如果存在则更新文档,否则创建它

Mongoose:过滤,如果存在则更新文档,否则创建它

Mongoose 子文档 - 未找到 ID

Mongoose VersionError:保存文档时未找到与 id 匹配的文档