如何更新 Node.js 中的一对多关系?

Posted

技术标签:

【中文标题】如何更新 Node.js 中的一对多关系?【英文标题】:How do you update one-to-many relationships in Node.js? 【发布时间】:2013-07-12 21:31:19 【问题描述】:

我正在开发一个使用 mongoosemongodbrestify 的 Node 应用程序。我想了解在定义路由函数时从各种模型中导入代码是否是一种好习惯。这应该是一个相当简单的问题,我只需要指导,我就能自己编写代码。感谢您抽时间阅读。

我知道如何定义这种关系,但我不确定我应该如何建立实际的关系。也就是说,换句话说,在创建汽车时,将汽车添加到其中的最佳方式是什么。

请注意,我正在尝试保持此 api RESTful。

我有两个模型,我必须根据以下架构链接它们,存储在db/schema.js

//schema.js
  var restify = require('restify');
  var mongoose = require('mongoose');
  var Schema = mongoose.Schema;
  var ObjectId = Schema.ObjectId;

// User Schema

  exports.User = new Schema(
    id: ObjectId,
    name: String,
    cars: [ type: ObjectId, ref: 'Car' ],
  );

// Car Schema

  exports.Car = new Schema(
    id: ObjectId,
    name: String,
    _user:  type: ObjectId, ref: 'User' ,
  );

然后我在models/... 中构建模型,每个模型都有不同的文件。现在它们每个只有一行代码,但我将它们作为独立文件保留,以供我需要编写模型方法时使用。

models/car.js:

  mongoose.model('Car', db_schema.Car);

models/user.js:

  mongoose.model('User', db_schema.User);

最后,我用帖子设置路由并将请求放入routes/cars.js

这还不是全部,只是回答我的问题所必需的。

  module.exports = function(app) 

    function putCar(req, res, next) 
      Car.findById(req.params.id, function (err, car) 
        if (!err) 
          car.name = req.params.name;
          car.save(function (err) 
            if (!err) 
             // PLACE A
             // current_user = get current user from session
             // current_user.cars.push(car);
              res.send(car);
              return next();
             else 
              return next(new restify.InternalError(err));
            
          );
         else 
          return next(new restify.MissingParameterError('ObjectId   required.'));
        
      );
     

    function postCar(req, res, next) 
      var car = new Car(req.params);
      car.save(function (err, car) 
        if (!err) 
          // PLACE B
          // current_user = get current user from session
          // current_user.cars.push(car);
          res.send(car);
         else 
          return next(err);
        
      );
    

    app.post('api/car', postCar);
    app.put('/api/car', putCar);
  

将伪代码之类的代码放在 A 和 B 位置是否合适?我想到的问题是我需要在 routes/cars.js 文件中需要 User 模型,这使得事情变得不那么模块化。在models/car.js中这样做会更好吗?

【问题讨论】:

我实际上既不会说 model.js 也不会说 routes/car.js。我会有一个文件来处理模型的实际保存、更新、添加等。为什么不把它放在路由中?好吧,这与路由无关,路由是用来获取请求并传递响应的,它不关心如何实际处理数据。 【参考方案1】:

我不同意您根本需要架构的假设。我相信 95% 的人在使用 Mongoose 时他们真的不需要它,因为这样定义模式的好处并没有超过人们使用它的缺点。如果在您的应用程序中验证数据对象与模式匹配有一些关键和不寻常的角色,那么可能会有所不同。但无论如何你必须在前端这样做,我只是不认为大多数系统真的需要在后端以不同的方式重复这项工作。

对于绝大多数情况,数据库相对较小且简单。你的情况可能也不例外。因此,让我们真正利用我们拥有无模式数据库并丢失样板的事实。

看起来您正计划为每个集合编写大量样板代码。不要那样做。相反,请查看一些适用于 Node 的 CRUD 系统,例如:https://github.com/AndrewRademacher/auto-crudDoes MongoDB have a native REST interface? 和/或您可以根据您的特定需求添加它们。

我认为这种关于将汽车添加到后端会话的用户对象的业务的一般理念的某些部分可能与安全性有关。换句话说,假设你不能只相信前端的话,并用它拥有的任何汽车来保存用户对象,因为有人可能试图破解前端。同样,对于绝大多数情况,我只是不认为这是一个明智的假设。

我认为,如果您只是在后端有一些通用的方法来执行 CRUD,并在前端将汽车添加到用户的数据对象中,那将会简单得多。如果您确实需要,您可以在通用 CRUD 系统之上在后端进行细粒度的安全性(即,有有效的业务理由,例如影响底线的事情)。

主要是从几乎所有数据库都基于 SQL 并且在后端具有带有静态语言的刚性模式时的保留信念系统,因此您几乎不得不使用一堆样板代码或依赖元编程这对于静态语言来说很棘手。

我认为,在 95% 的情况下,既然我们已经有了 JSON 和动态语言之类的东西,那么拥有一堆仅通过实体(有时是字段名称)来区分的样板文件是错误的。

【讨论】:

非常感谢您的回复!我现在正在工作,但我会深入了解一下并尽快回复您。 我完全同意杰森的观点。我强烈建议避免使用猫鼬。我从事过一个实质性的 node-mongo 项目。我们最终不得不淘汰 mongoose,因为它妨碍了执行高级查询。【参考方案2】:

我会提出两个建议:

    如果您希望其余功能相对较大,请将路由文件中的功能代码抽象到控制器中。

    或者,您可以围绕每个表创建自己的 DAO(数据库访问对象)包装器,然后在更简单的路由文件中进行调用时将它们视为 javascript 对象而不是表。

【讨论】:

以上是关于如何更新 Node.js 中的一对多关系?的主要内容,如果未能解决你的问题,请参考以下文章

使用 laravel,我如何创建一个将更新一对多关系的视图?

核心数据:NSPredicate 一对多对多关系

如何描述 Coq 中的一对多关系?

如何从一对多单向关系中获取“多”部分中的对象?

如何过滤graphQL一对多关系中的查询?

Spring Boot REST Api中的一对多关系