簡體   English   中英

在 Vapor 的 Fluent 中查詢嵌套的子級

[英]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。 所以你有幾個選擇:

  1. 按照尼克的建議使用急切加載。 這將更有效率,因為它只有 2 個 DB 查詢而不是 N+1。

  2. 使用 async/await 來寫你想要的

  3. 妥善處理期貨。 而不是使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM