【问题标题】:Express.js & Mongoose: access Object attribute name by the request parameterExpress.js & Mongoose:通过请求参数访问对象属性名
【发布时间】:2017-11-11 17:32:47
【问题描述】:

背景

问题是我想通过请求中传递的变量来访问对象的属性。发出 GET /modify/:var 请求以修改 MongoDB 中已保存文档的属性。要知道文档的哪个属性,在获取时转换为对象,我们要修改,我们需要在 :var 中传递的字符串。

路线

 public modify(req: express.Request, res: express.Response, next: express.NextFunction)
  {
    Model.findOne({attr: true}, (err, result) => {
      if (err) {
        console.log(err);
      }
      else {
        let copy = result;
        copy.attr.one.(req.params.var) = false; // here
      }
    });
  }

更新

在 Paul 的回答之后,我编辑了我的代码,它返回了 500 状态代码。我编辑了

router.put('/route/:var')

public mock(req: express.Request, res: express.Response, next: express.NextFunction) {
      Model.findOne({attr: false}, (err, doc) => {
        doc.attr[req.params.var] = false;
        model.save((e) => {
        if (e){
        console.log(e);
        }
          res.send(doc);
        });
    });

模型结构

export interface Model extends mongoose.Document {
  attr: {
             one:   {value: Boolean},
             two:   {value: Boolean},
             three: {value: Boolean},
             four:  {value: Boolean},
           };

}

【问题讨论】:

  • 我不知道你想做什么。你能试着解释一下吗?
  • @Paul 发出 GET /modify/:var 请求以修改 MongoDB 中已保存文档的属性。要知道文档的哪个属性,在获取时转换为对象,我们想修改,我们需要在 :var 中传递的字符串。
  • 我认为你还没有理解。您正在执行的 Model.findOne() 只会找到第一个将“attr”属性设置为 false 的文档(如果有的话)。如果 doc.attr 是一个布尔值(在您的示例中必须如此),那么您不能使用括号表示法来访问其上的任何内容,例如 doc.attr['some-string'],这将引发错误。跨度>
  • @Paul 根据给定的模型结构,是不是可以通过 doc.attr['one'].value 访问值?
  • 有可能,如果 doc.attr 是一个对象。如果您能够通过查询{ attr:false } 找到该对象,则不是。

标签: node.js mongodb express typescript mongoose


【解决方案1】:

好的,首先,您应该使用 GET 请求来修改任何 GET 请求应该只是查询的内容,而不更改服务器上的任何内容。

您要查找的是 PUT 请求,用于修改现有资源。

其次,您正在尝试修改一个对象,但实际上您还没有对象。你的 findOne 必须有一些东西可以查询。如果你有一个像http://example.com/modify/name 这样的 URL,你期望会发生什么?没有办法告诉 您正在修改哪个 名称或您将其修改为什么。

即使您只是按照您的建议进行布尔运算,采用给定的布尔变量并将其设置为 false,您的 URL 也不会告诉您 哪个 模型应该将此变量设置为 false。

相反,您可以将其设置为向(例如)/things/:thingId(其中 thingId 是您正在建模的任何给定事物的唯一标识符)发出 PUT 请求。这将要求您的客户端在请求正文中发送所有可更新的属性。

或者,如果您想允许它只修改所选事物的一个属性,您可以将 PUT 设置为/things/:thingId/:attr。在这种情况下,您的处理程序将如下所示:

app.put('/things/:thingId/:attr', (req, res, next) => {
  // note, I normally do this kind of thing in an `app.param()` or `router.param()` call.  Included here for brevity.
  Thing.findById(req.params.thingId, (err, thing) => {
     thing[req.params.attr] = req.body[attr];
     thing.save((e) => {
        // todo: handle the error
        res.send(thing);
     });
  });
});

正如我所说,这里的回调比我通常做的要嵌套更多,但希望您能大致了解。

【讨论】:

  • 谢谢,您的通用解决方案可能有效。我不确定的是,猫鼬如何知道 :attr 将归因于 req.body 而不是 req.params?在我的例子中,数据库中有一个文档可以知道,但我理解使用 URL 中提供的 id 和模型中的 id 属性进行搜索的一般想法。因此,我可以使用 findOne(),但我面临 500 状态响应。如果你想看看,我编辑了我的问题。
  • Mongoose 不知道,Express 根据您的配置方式知道。 req.params 由 URL 中的内容填充(您的 url 模式 /models/:attr 将导致 :attr 的实际 url 中的任何内容将作为 req.params.attr 的值放置。)。 req.body 由 body-parser 模块提取的内容填充。
  • 我不确定正文解析器在代码中的哪个位置填充 req.body
  • 我无权访问您的代码,但在大多数快速应用程序中,您会安装 body-parser 模块,然后 app.use 它作为中间件。
  • 如果您使用的是 GET,那么您将不会发送正文。这就是为什么我说使用 PUT,它确实有一个 body。 URL 参数为您提供所需的属性名称。所以考虑一下,一个 PUT 到 /model/123/lastname 的正文为“lastname=Schmoe”。我的路线示例中的req.params.thingId 将等于“123”,而req.params.attr 将等于“姓氏”。 req.body(如果您使用的是bodyParser.urlencoded 中间件)将有一个密钥req.body.lastname,它等于“Schmoe”。不过,由于它是动态的,您可以通过说 req.body[req.params.attr] 来获得它。
【解决方案2】:

你有查询表达式错误

Model.findOne({attr: {$exists:true}}, (err, result) => {
      if (err) {
        console.log(err);
      }
      else {
        let copy = result;
        copy.attr.(req.params.var) = false; // here
      }
    });

【讨论】:

  • 感谢您的回答,但这不起作用。问题确实出在 cop.attr.(here) 中。 IDE 可以在编译前检测到表达式会产生 TS2364: Invalid left-hand side of assignment 错误。
猜你喜欢
  • 2013-06-06
  • 1970-01-01
  • 2016-07-22
  • 2014-04-25
  • 2021-05-21
  • 2014-09-19
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多