首页 文章

Angularjs:通过关系实现多对多

提问于
浏览
1

在我的应用程序中,我有 Students 谁可以 EnrollClasses .

Enrollment 记录 start and end dates 以及 Class 的引用 .

Class has details 喜欢类名和描述 .

学生(1) - (N)入学(1) - (1) class 因此学生(1) - (N) class

这就是我想要的对象 .

{
  "studentId": 1,
  "name": "Henrietta",
  "enrolledClasses": [
    {
      "enrollmentId": 12,
      "startDate": "2015-08-06T17:43:14.000Z",
      "endDate": null,
      "class": 
        { 
          "classId": 15,
          "name": "Algebra",
          "description": "..."
        }
    },
      "enrollmentId": 13,
      "startDate": "2015-08-06T17:44:14.000Z",
      "endDate": null,
      "class": 
        {
          "classId": 29,
          "name": "Physics",
          "description": "..."
        }
    }
}

但是我的RESTful API不能(轻松地)输出关系的完整嵌套结构,因为它的ORM不能通过关系做多对多 . 所以我得到了学生和他们的多个入学人数,但只提到每个人的课程,而不是细节 . 我需要显示细节,而不仅仅是Id .

我可以等待学生对象可用,然后使用引用为每个classId进行额外的API调用以获取详细信息,但不确定如何,甚至是否将其与学生对象集成 .

这就是我到目前为止所拥有的 .

function findOne() {
  vm.student = StudentsResource.get({
    studentId: $stateParams.studentId
  });
};

这是我从API中获取的内容

{
  "studentId": 1,
  "name": "Henrietta",
  "enrolledClasses": [
    {
      "enrollmentId": 12,
      "startDate": "2015-08-06T17:43:14.000Z",
      "endDate": null,
      "class": 15
    },
      "enrollmentId": 13,
      "startDate": "2015-08-06T17:44:14.000Z",
      "endDate": null,
      "class": 29
    }
}

对于课程详细信息,我可以一次一个,但还没有想出如何等待学生对象将其推入其中 . 也不是如何正确推动它们......

{ 
  "classId": 15,
  "name": "Algebra",
  "description": "..."
}

{
  "classId": 29,
  "name": "Physics",
  "description": "..."
}

问题

Is it good practice to combine the student and class(es) details through the enrollments, as one object?

  • 如果是这样,最明确的方式是什么?

  • 如果没有,那么另一种有效的方法是什么?

请记住,该应用程序将允许更改学生的详细信息和注册,但不应允许更改类名称或说明的详细信息 . 因此,如果Angular要为对象发送PUT,则不应尝试发送任何类的详细信息,仅发送引用 . 这将强制服务器端保护数据,但为避免错误,客户端不应该尝试 .

对于后台,我使用SailsJS和PostgreSQL作为后端API .

1 回答

  • 1

    所以基本上在Sailsjs方面你应该覆盖StudentController.js中的findOne函数 . 这是假设您正在使用蓝图 .

    // StudentController.js
    module.exports = {
      findOne: function(req, res) {
        Student.findOne(req.param('id')).populate('enrollments').then(function(student){
          var studentClasses = Class.find({
            id: _.pluck(student.enrollments, 'class')
          }).then(function (classes) {
            return classes
          })
          return [student, classes]
        }).spread(function(student, classes){
          var classes = _.indexBy(classes, 'id')
          student.enrollments = _.map(student.enrollments, function(enrollment){
            enrollment.class = classes[enrollment.class]
            return enrollment
          })
          res.json(200, student)
        }).catch(function(err){
          if (err) return res.serverError(err)
        })
      }
    }
    
    // Student.js
    
    module.exports = { 
      attributes: {
        enrollments: {
          collection: 'enrollment',
          via: 'student'
        } 
        // Rest of the attributes..   
      }
    }
    
    // Enrollment.js
    
    module.exports = {
      attributes: {
        student: {
          model: 'student'
        }
        class: {
          model: 'class'
        }
        // Rest of the attributes...
      }
    }
    
    // Class.js
    
    module.exports: {
      attributes: {
        enrollments: {
          collection: 'enrollment',
          via: 'class'
        }
        // Rest of the attrubutes
      }
    }
    

    说明:
    1.使用Lo-dash的_.pluck函数返回一个classIds数组,我们找到了我们想要填充的所有类 . 然后我们使用promise chain .spread(),创建一个由classid索引的数组,并将classIds映射到我们想要填充到Student.findOne()返回的学生的注册中的实际类实例 .
    2.让学生注册参加人数充足的课程 .

    来源:Sails.js populate nested associations

相关问题