Vapor 4:如何包含兄弟姐妹,包括数据透视表中的额外属性?

Kev*_*ers 1 swift vapor vapor-fluent

我在如何通过包含额外字段的数据透视表返回包含多对多关系的模型方面遇到了很多困难。基本上,我想返回带有额外字段的完整数据透视表,但我不知道如何执行此操作。

让我们考虑以下 3 个模型:CourseUser,以及它们之间的枢轴 a Student。该Student模型包含额外的字段progress

final class Course: Model, Content {
  static let schema = "courses"

  @ID(key: .id)
  var id: UUID?

  @Field(key: "name")
  var name: String

  init() { }
}

final class Student: Model {
  static let schema = "students"

  @ID(key: .id)
  var id: UUID?

  @Parent(key: "course_id")
  var course: Course

  @Parent(key: "user_id")
  var user: User

  @Field(key: "progress")
  var progress: Int

  init() { }
}

final class User: Model, Content {
  static let schema = "users"

  @ID(key: .id)
  var id: UUID?

  @Field(key: "name")
  var name: String

  @Field(key: "private")
  var somePrivateField: String

  init() { }
}
Run Code Online (Sandbox Code Playgroud)

我有一条这样的路线,它返回一系列课程:

func list(req: Request) throws -> EventLoopFuture<[Course]> {
  return Course
    .query(on: req.db)
    .all()
    .get()
}
Run Code Online (Sandbox Code Playgroud)

生成的 JSON 看起来像这样:

[
  {
    "id": 1,
    "name": "Course 1"
  }
]
Run Code Online (Sandbox Code Playgroud)

我怎样才能包含学生数组,以便最终结果是这样的?

[
  {
    "id": 1,
    "name": "Course 1",
    "students": [
      {
        "user": {
          "id": 1,
          "name": "User 1"
        },
        "progress": 0
      },
      {
        "user": {
          "id": 2,
          "name": "User 2"
        },
        "progress": 100
      },
    ]
]
Run Code Online (Sandbox Code Playgroud)

我可以将用户添加到Course模型中,如下所示:

@Siblings(through: Student.self, from: \.$course, to: \.$user)
public var users: [User]
Run Code Online (Sandbox Code Playgroud)

然后像这样改变我的路线:

func list(req: Request) throws -> EventLoopFuture<[Course]> {
  return Course
    .query(on: req.db)
    .with(\.$user)
    .all()
    .get()
}
Run Code Online (Sandbox Code Playgroud)

但这只会将用户信息添加到结果中,而不是数据透视表上的额外属性(即progress)。在我看来,尽管数据透视表可以具有额外的属性,并且文档甚至特别指出,但实际上没有好的方法来处理这种情况,因为@Siblings根本不指向数据透视表。

额外问题:我希望将User模型映射到PublicUser模型,以便私有/内部字段不是 JSON 结果的一部分。看这个问题就明白我的意思了。我想做同样的事情,但是使用学生枢轴的用户模型。复杂,我知道

Nic*_*ick 5

我在访问数据透视表中的其他字段时遇到了同样的问题,但有一种相当简洁的方法可以完成此任务。除了兄弟姐妹关系之外,还定义一个@Children关系 fromCourseStudent。然后,在您的查询中,执行嵌套with.

将其放入您的课程模型中:

@Children(for:\.$course) var students: [Student]
Run Code Online (Sandbox Code Playgroud)

询问:

let query = Course.query(on: req.db).with(\.$students){ $0.with(\.$user) }.all()
Run Code Online (Sandbox Code Playgroud)

第一个with获取数据透视表的附加字段,然后嵌套with获取User模型。