我试图为我的问题做一个我能想到的最基本的例子。我有一个Course
模型和一个多对多表,User
其中还存储了一些额外的属性(progress
在下面的示例中)。
import FluentPostgreSQL
import Vapor
final class Course: Codable, PostgreSQLModel {
var id: Int?
var name: String
var teacherId: User.ID
var teacher: Parent<Course, User> {
return parent(\.teacherId)
}
init(name: String, teacherId: User.ID) {
self.name = name
self.teacherId = teacherId
}
}
struct CourseUser: Pivot, PostgreSQLModel {
typealias Left = Course
typealias Right = User
static var leftIDKey: LeftIDKey = \.courseID
static var rightIDKey: RightIDKey = \.userID
var id: Int?
var courseID: Int
var userID: UUID
var progress: Int
var user: Parent<CourseUser, User> {
return parent(\.userID)
}
}
现在,当我返回一个Course
对象时,我希望 JSON 输出是这样的:
{
"id": 1,
"name": "Course 1",
"teacher": {"name": "Mr. Teacher"},
"students": [
{"user": {"name": "Student 1"}, progress: 10},
{"user": {"name": "Student 2"}, progress: 60},
]
}
而不是我通常会得到的,这是:
{
"id": 1,
"name": "Course 1",
"teacherID": 1,
}
所以我创建了一些额外的模型和一个函数来在它们之间进行转换:
struct PublicCourseData: Content {
var id: Int?
let name: String
let teacher: User
let students: [Student]?
}
struct Student: Content {
let user: User
let progress: Int
}
extension Course {
func convertToPublicCourseData(req: Request) throws -> Future<PublicCourseData> {
let teacherQuery = self.teacher.get(on: req)
let studentsQuery = try CourseUser.query(on: req).filter(\.courseID == self.requireID()).all()
return map(to: PublicCourseData.self, teacherQuery, studentsQuery) { (teacher, students) in
return try PublicCourseData(id: self.requireID(),
name: self.name,
teacher: teacher,
students: nil) // <- students is the wrong type!
}
}
}
现在,我快到了,但我无法studentsQuery
从转换EventLoopFuture<[CourseUser]>
为EventLoopFuture<[Student]>
. map
我尝试了and的多种组合flatMap
,但我不知道如何将一组 Futures 转换为一组不同的 Futures。