Javascript 快速路由器:转换为ObjectId错误

Javascript 快速路由器:转换为ObjectId错误,javascript,node.js,express,mongoose,Javascript,Node.js,Express,Mongoose,调用用户/状态路由时,我遇到以下错误: 我正在使用find mongoose方法获取所有符合条件的文档。现在find的id与findById不同 奇怪的是,我唯一能修复它的方法就是移动我的Express Router定义。见下文 这种方法不起作用: 这种方法是有效的:注意用户/状态和用户/:id是如何交换的 // users router .route('/users') .get(getAll) .post(createNew); router .route('/users/stat

调用用户/状态路由时,我遇到以下错误:

我正在使用find mongoose方法获取所有符合条件的文档。现在find的id与findById不同

奇怪的是,我唯一能修复它的方法就是移动我的Express Router定义。见下文

这种方法不起作用:

这种方法是有效的:注意用户/状态和用户/:id是如何交换的

// users
router
 .route('/users')
 .get(getAll)
 .post(createNew);

router
 .route('/users/status')
 .get(status);

router
 .route('/users/:id')
 .put(updateExisting)
 .get(getOne)
 .post(upload.single('proposal'), uploadFile);
用户/状态的控制器:

仅供参考:我正在运行mongoose v4.13.4和express v4.15.5


我不确定我做错了什么。似乎我在某个地方犯了一个愚蠢的错误。

第二种路由技术是正确的

第一个路由排序的问题是,您的.route'/users/:id'在路由.route'/users/status'之前匹配,因为url路径/users/status满足路由/users/:id。 实际上,如果在/user/path之后传递任何内容,例如,/users/anythingHere将由/users/:id路由匹配


这就是Express.js的工作方式。您定义的管线将按其定义的顺序依次匹配。因此,您的第二个路由设置是正确的。

第二个路由技术是正确的

第一个路由排序的问题是,您的.route'/users/:id'在路由.route'/users/status'之前匹配,因为url路径/users/status满足路由/users/:id。 实际上,如果在/user/path之后传递任何内容,例如,/users/anythingHere将由/users/:id路由匹配


这就是Express.js的工作方式。您定义的管线将按其定义的顺序依次匹配。因此,您的第二个路由设置是正确的。

这是详细阐述REST API设计的答案,Joytman Singh的答案是正确的,因此我不再详细阐述

您遇到的问题基本上告诉您REST设计不正确。URL不应该由两个控制器使用,并且顺序不应该对某些前置处理程序、后置处理程序有影响,但对于具有相同重要性的控制器和类似的服务,URL不应该有影响

例如,如果两个控制器能够捕获相同的URL,则第一个控制器会捕获该URL,发送响应并通常结束链。有可能你甚至没有注意到。删除第一个时会发生什么?好吧,您希望在该URL上获得404,而不是这个,它将开始执行不同的代码。你不要这个

标准REST API设计基本上是这样的:/collection/id/collection/id…,在现实世界中,您可以拥有例如/users/34/images

如果您想要列表,请停在collection/users/34/images;如果您想要详细信息,请停在id/users/34

如果您需要例如“仅查找存在的用户”之类的筛选器,则应使用查询字符串/users?exist=true来完成此操作。然后在基于这些选项的控制器中,使用if req.query.exist='true',可以执行不同的操作,但应该有一个控制器来处理它


如果您需要连接到用户的非常特殊的东西,但它不返回用户对象,那么最好创建完全不同的URL,如/statuses/users,其中用户是状态的id或类似/statuses?users=1这是详细阐述REST API设计的答案,乔伊特曼·辛格的回答是正确的,因此我不再详细阐述

您遇到的问题基本上告诉您REST设计不正确。URL不应该由两个控制器使用,并且顺序不应该对某些前置处理程序、后置处理程序有影响,但对于具有相同重要性的控制器和类似的服务,URL不应该有影响

例如,如果两个控制器能够捕获相同的URL,则第一个控制器会捕获该URL,发送响应并通常结束链。有可能你甚至没有注意到。删除第一个时会发生什么?好吧,您希望在该URL上获得404,而不是这个,它将开始执行不同的代码。你不要这个

标准REST API设计基本上是这样的:/collection/id/collection/id…,在现实世界中,您可以拥有例如/users/34/images

如果您想要列表,请停在collection/users/34/images;如果您想要详细信息,请停在id/users/34

如果您需要例如“仅查找存在的用户”之类的筛选器,则应使用查询字符串/users?exist=true来完成此操作。然后在基于这些选项的控制器中,使用if req.query.exist='true',可以执行不同的操作,但应该有一个控制器来处理它

如果您需要连接到的非常特殊的东西,即用户,但它不返回users对象,那么最好创建完全不同的URL,如/statuses/users,其中users是statuses的id或类似/statuses?users=1的id,/users/status将此/users/:id与id一起填充=status@libiks

o在/users/:id之后的任何路由都将尝试满足参数:id。因此,这些路由的顺序很重要?在您的情况下,顺序很重要,如果顺序很重要,通常意味着您的设计很糟糕。对于标准REST,有/collections/id/collections/id/collections/id。您应该有endpoint/users,并使用exists=true这样的查询字符串,并将其称为/users?exists=true或/users?status=true@libik谢谢你的帮助!谢谢你!!!我不确定这种情况下的设计是否糟糕。如果我错了,请纠正我。我使用Express.js处理所有路由。如果我们传递给app.VERB的第一个参数包含查询字符串,例如/?debug=true,那么Express.js将忽略该信息。例如,app.get'/?debug=true',routes.index;将被完全视为app.get“/”,routes.index;。访问查询字符串的唯一方法是express中的req.Query。这有点让人困惑,/users/status将这个/users/:id与id混合在一起=status@libik因此,在/users/:id之后的任何路由都将尝试满足一个参数:id。那么这些路由的顺序很重要吗?在您的情况下,顺序很重要,如果顺序很重要,通常意味着您的设计很糟糕。对于标准REST,有/collections/id/collections/id/collections/id。您应该有endpoint/users,并使用exists=true这样的查询字符串,并将其称为/users?exists=true或/users?status=true@libik谢谢你的帮助!谢谢你!!!我不确定这种情况下的设计是否糟糕。如果我错了,请纠正我。我使用Express.js处理所有路由。如果我们传递给app.VERB的第一个参数包含查询字符串,例如/?debug=true,那么Express.js将忽略该信息。例如,app.get'/?debug=true',routes.index;将被完全视为app.get“/”,routes.index;。访问查询字符串的唯一方法是express中的req.Query。这有点让人困惑。啊,好的。我不知道。这很有帮助。因此,它们需要按照一定的顺序进行。有关于这方面的文件吗?我在express网站上找不到任何东西。谢谢你的帮助!!!快速提问:为什么交换它们不会导致相同的问题?因此,如果我在第二种技术中访问users/:id路由,它是否也会给我一个错误?不幸的是,我认为Express.js在文档中没有阐明这一点。关于您的问题-在第二种情况下,如果您的url路径不是/users/status,那么它将与route/users/:id.Ah匹配。我不知道。这很有帮助。因此,它们需要按照一定的顺序进行。有关于这方面的文件吗?我在express网站上找不到任何东西。谢谢你的帮助!!!快速提问:为什么交换它们不会导致相同的问题?因此,如果我在第二种技术中访问users/:id路由,它是否也会给我一个错误?不幸的是,我认为Express.js在文档中没有阐明这一点。关于您的问题-在第二种情况下,如果您的url路径不是/users/status,那么它将由route/users/:id匹配。非常感谢。这很有帮助!在我的控制器中使用if req.query.exist='true'是否会使控制器代码非常繁忙?这就是它的本意吗?。我假设我们会有一些if语句,因为我们可以对像用户这样的资源执行数字查询。另外,您是否知道任何在线资源可能会讨论良好的REST设计?我只是想确保我遵守最佳实践,如果我问的问题太多,我会道歉。@Skywalker-不,当你要求exist=true时,你必须以某种方式告诉你的程序,它到底意味着什么,因此你必须以某种方式告诉它。即使是不同的URL,如果它基本上意味着,如果URL是这样的,那么只查找已经存在=true的用户。但是把属于你的东西真正地放在一起是件好事。其原理称为松耦合和高内聚。它通常用于几乎所有的东西和不同级别的模块、类、控制器。。。我现在不知道我能推荐什么特别的链接,只要看看谷歌就可以了。@Skywalker-之前的评论中没有对控制器代码的反应。实际上,控制器应该只将这些参数传递给服务方法设置,即booleans findExist为true,服务方法应该负责调用代码中更深层的适当方法。控制器本身应该只解析输入/输出,并以服务方法能够理解的方式将其提供给服务方法。控制器和服务方法都需要某种if。感谢您的反馈。您让我对REST最佳实践有了很好的基本了解,也让我知道了我做错了什么。我找到了一个似乎很详细的方法。再次感谢!非常感谢。这很有帮助!在我的控制器中使用if req.query.exist='true'是否会使控制器代码非常繁忙?这就是它的本意吗?。我想我们会有一些if语句beca
使用我们可以对像用户这样的资源执行数字查询。另外,您是否知道任何在线资源可能会讨论良好的REST设计?我只是想确保我遵守最佳实践,如果我问的问题太多,我会道歉。@Skywalker-不,当你要求exist=true时,你必须以某种方式告诉你的程序,它到底意味着什么,因此你必须以某种方式告诉它。即使是不同的URL,如果它基本上意味着,如果URL是这样的,那么只查找已经存在=true的用户。但是把属于你的东西真正地放在一起是件好事。其原理称为松耦合和高内聚。它通常用于几乎所有的东西和不同级别的模块、类、控制器。。。我现在不知道我能推荐什么特别的链接,只要看看谷歌就可以了。@Skywalker-之前的评论中没有对控制器代码的反应。实际上,控制器应该只将这些参数传递给服务方法设置,即booleans findExist为true,服务方法应该负责调用代码中更深层的适当方法。控制器本身应该只解析输入/输出,并以服务方法能够理解的方式将其提供给服务方法。控制器和服务方法都需要某种if。感谢您的反馈。您让我对REST最佳实践有了很好的基本了解,也让我知道了我做错了什么。我找到了一个似乎很详细的方法。再次感谢!
// users
router
 .route('/users')
 .get(getAll)
 .post(createNew);

router
 .route('/users/:id')
 .put(updateExisting)
 .get(getOne)
 .post(upload.single('proposal'), uploadFile); 

router
 .route('/users/status')
 .get(status);
// users
router
 .route('/users')
 .get(getAll)
 .post(createNew);

router
 .route('/users/status')
 .get(status);

router
 .route('/users/:id')
 .put(updateExisting)
 .get(getOne)
 .post(upload.single('proposal'), uploadFile);
let status = (req,res) => {

  User.find({usersProposals: {$exists: true, $not: {$size: 0}}})
     .exec()
     .then((data) => {sendJsonResponse(res, 200, data)})
     .catch(err => {sendJsonResponse(res, 500, err)})

 };