/ / Načítavam všetky polia zo spoločného dotazu vo Vapor 3 - mysql, swift, vapor, vapor3

Načítavanie všetkých polí zo spojeného dotazu vo Vapor 3 - mysql, swift, para, vapor3

Pozadie

Vzhľadom na nasledujúce vzorové modely (vybrané 2 jednoduché príklady, ktoré ukazujú vzťah 1-n):

final class Company: MySQLModel {
var id: Int?
var name: String
}

final class Client: MySQLModel {
var id: Int?
var attr1: Int
var attr2: String
var companyId: Company.ID

static func prepare(on connection: MySQLDatabase.Connection) -> Future<Void> {

return Database.create(self, on: connection, closure: { builder in
try addProperties(to: builder)
builder.addReference(from: .companyId, to: Company.id, actions: .update)
})
}
}

otázka

Existuje spôsob, ako načítať a vrátiť výsledok aSPOLOČNÝ dopyt (napr .: Spoločnosť - Klient // Individuálny počet) bez potreby prvotných dopytov? Snažil som sa používať dopyt a vzťahy, ale neexistuje spôsob, ako ich všetky získať jedným pokusom.

V ideálnom prípade by vrátené údaje mali vnorenú štruktúru, ako napríklad:

očakáva:

{
"name": "Alice",
"id": 0000000001,
"company": {
"id": 11111111,
"name": "Stack Overflow"
}
}

Riešenie (aka riešenie)

Podarilo sa mi to „fungovať“ tak, že som použil dodatočnú štruktúru (nazýva sa Wrapper, Box, Merged atď.), Ktorá držala všetky entity, a nakoniec pomocou makeJSON vráti ju do kontroléra.

    let query = try db.query(Client.self)
.filter(.attr1 > 123)
.filter(.attr2 == "abc")
let client = try query.first()

// client.company is just an attribute of Client that uses
// the *parent* method to retrieve it
if let client = client, let company = try client.company.get() {

// others uses *children* method
let others = try client.others.limit(5).all()

let companyJSON = company.dictionary! // dictionary returns [String:Any] for any Encodable
let clientJSON = client.dictionary!


let merged = clientJSON.merging([ "company": companyJSON ], uniquingKeysWith: { (first, _) in first })
return merged
}

Záverečné pripomienky

Je použitie jednotky wrapper jediným spôsobom, ako to urobiť (bez použitia nespracovaných dopytov)? Riešenie viacúrovňových výsledkov by bolo skutočne únavné.

Edit: Už som našiel súvisiacu otázku Je možné získať prístup k poliam v spoločnej tabuľke vo Vapor? ale odpoveď nefungovala rovnako, ako chcem.

Edit2: Nedávno som prešiel na Vapor3, teda nový kód. Myslím si, že Vapor2 by bol rovnaký nápad, ale vy ste museli napísať trochu viac kódu, pretože Vapor3 predstavil podporu Codable.

odpovede:

3 pre odpoveď č. 1

Nie som si istý, či ste to úplne vyhľadám, ale myslím, že som sa snažil urobiť niečo podobné. Chcel som ukázať tabuľku používateľov a ich priradených tokenov autorizácie. Toto je nastavené štandardným spôsobom, pričom v programe Fluent je nastavený vzťah rodič-dieťa (jeden-k-veľa). Nakoniec som robil nasledujúce, čo funguje celkom dobre

func getUsersHandler(_ req: Request) throws -> Future<View> {
return User.query(on: req).all().flatMap(to: View.self) { users in
let tokenFutures = try users.map {
return try $0.authTokens.query(on: req).all()
}
return tokenFutures.flatMap(to: View.self) { tokensByUser in
let usersAndTokens = zip(users, tokensByUser).map {
return UserAndTokens(user: $0, tokens: $1.map { $0.token})
}
let listUsersCtx = ListUsersContext(usersAndTokens: usersAndTokens)
return try req.leaf().render("users", listUsersCtx)
}
}
}

Učím sa iba Vapor, takže nemám tušenie, či to tak jeje skvelé riešenie alebo nie. Tým, že umožníme používateľom sľúbiť vyriešenie, a potom nechám každého sľubovať vyriešenie každého používateľa -> token, všetko zostane asynchrónne až do konca, keď zabalím všetky vyriešené veci spolu do kódovateľnej štruktúry ListUsersContext.


0 pre odpoveď č. 2

Chvíľu som to premýšľal, potom som včera videl, že to bolo niekedy pridané k dokumentácii: https://docs.vapor.codes/3.0/fluent/querying/#join

Mali by ste byť schopní urobiť niečo také

Client.query(on: conn).join(Client.companyId, to: Company.id)
.filter(.attr1 > 12)
.filter(Company.name == "ACME")
.alsoDecode(Company.self)
.all()

To by vám malo vrátiť rad tuplov (klient, spoločnosť). Mali by ste byť schopní ľahko ich zoskupiť do JSON, ktorý si želáte, a nebude sa to týkať

Ešte som nekontroloval, či bude viac inštancií tej istej spoločnosti rovnakých.