fluentを使用して2つのテーブルを結合する方法を理解するのに苦労しています。本質的に、私はこのSQLコマンドを実行したいと思います。
SELECT p.name, o.amount, o.amount * p.amount total
FROM "OrderPoints" o
INNER JOIN "Points" p ON o.points_id = p.id
WHERE order_id = 10831
2つのモデルを次のように設定しました。
final class OrderPoint: Codable, PostgreSQLModel, Content, Migration {
var id: Int? = nil
var orderID: Order.ID
var pointID: Point.ID
var amount: Double = 0
var point: Parent<OrderPoint, Point> {
return parent(\.pointID)
}
}
final class Point: Codable, PostgreSQLModel, Content, Migration {
var id: Int? = nil
var name: String
var abbrev: String
var amount: Double
}
そのため、コントローラーで、気になるすべての注文をループします。
// SELECT * FROM orders WHERE "month" = '2018-05-01'
let orders = try Order.query(on: req).filter(\Order.month == month).all()
return orders.flatMap(to: View.self) { orders in
let content = try orders.map { (order) -> OrderIndexContent in
let values = try order.orderPoints.query(on: req).all()
これでorder_points
現在のIDのすべてのアイテムが取得されると思いますが、Points
モデルと結合して残りのクエリを実行する方法がわかりません(つまり、乗算された金額とポイント名を取得します)。
Order
は複数のOrderPoint
アイテムがあります。OrderPoint
あり、単一 Point
のアイテムを。Point
は多くのOrderPoint
アイテムを指す可能性があります。ですから、流暢とは物事を指すと私が思う方法でOrderPoints
は、多対多ではないので、ピボットではありません。
以下は機能しているようですが、これが大量の余分なSQL呼び出しになるため、これが「正しい」方法である方法はありません。
_ = try! order.orderPoints
.query(on: req)
.all()
.map(to: Void.self) { pointsForOrder in
pointsForOrder.forEach { orderPoint in
_ = try! orderPoint.point.get(on: req).map(to: Void.self) {
print("\(order.id!) \(order.name) \($0.abbrev) \(orderPoint.pointID) = \(orderPoint.amount) = \($0.amount * orderPoint.amount)")
}
}
}
でPoint
参照されているすべてのをから取得するには、クエリを実行して結合OrderPoint
するOrder
必要があります。次に、クエリする順序のフィルタリングにフィルターを追加できます。Point
OrderPoint
OrderPoint
これにより、次のFluentクエリが生成されます。
Point.query(on: req)
.join(field: \OrderPoint.pointID)
.filter(OrderPoint.self, \OrderPoint.orderID == order.id!)
.all()
ただし、このクエリはPoint
sの配列のみを返すためOrderPoint
、Discordに関する説明で指摘したように、デコードする必要があるという情報を見逃してしまいますOrderPoint
。幸い、Fluentにはこのための優れたメソッドがあります.alsoDecode
。したがって、最終的なクエリは次のようになります。
Point.query(on: req)
.join(field: \OrderPoint.pointID)
.filter(OrderPoint.self, \OrderPoint.orderID == order.id!)
.alsoDecode(OrderPoint.self)
.all()
これは、Point
との両方を含むタプルを返しますOrderPoint
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加