[英]Querying nested children in Vapor's Fluent
环境:蒸汽/流利的 4.0.0
我有一个带有 model 的树状结构数据,如下所示:
final class Ingredient: Model {
static let schema = "ingredients"
@ID(key: "id")
var id: UUID?
@Field(key: "name")
var name: String
@OptionalParent(key: "parent_id")
var parent: Ingredient?
@Children(for: \.$parent)
var children: [Ingredient]
}
我想在 API 方法之一中将整个树作为 JSON 返回。
func index(req: Request) throws -> EventLoopFuture<[APIIngredient]> {
// Gathering top-level nodes without parents
let ingredients = try Ingredient.query(on: req.db)
.filter(\.$parent.$id == nil)
.sort(\.$name)
.all()
.wait()
enter code here
// Creating API models
let apiIngredients = try ingredients.map {
try APIIngredient(
ingredient: $0,
childrenGetter: {
try $0.$children.query(on: req.db).all().wait()
}
)
}
return req.eventLoop.future(apiIngredients)
}
但我发现 .wait() 不允许在请求处理程序中使用。 解决这个问题的正确方法是什么?
wait()
是不允许的,因为它阻塞了 EventLoop。 所以你有几个选择:
按照尼克的建议使用急切加载。 这将更有效率,因为它只有 2 个 DB 查询而不是 N+1。
使用 async/await 来写你想要的
妥善处理期货。 而不是使用wait()
开关来处理期货:
func index(req: Request) throws -> EventLoopFuture<[APIIngredient]> {
// Gathering top-level nodes without parents
return Ingredient.query(on: req.db)
.filter(\.$parent.$id == nil)
.sort(\.$name)
.all()
.flatMap { ingredients in
ingredients.map { ingredient -> EventLoopFuture<APIIngredient>
let future = ingredient.$children.query(on: req.db).all().map { children in
APIIngredient(ingredient: ingredient, children: children)
}
}.flatten(on: req.eventLoop)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.