Делать соединения с Fluent в приложении Vapor - PullRequest
0 голосов
/ 19 мая 2018

Я изо всех сил пытаюсь понять, как соединить мои две таблицы вместе, используя свободное владение.По сути, я хочу выполнить эту команду 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

У меня есть две мои настройки, настроенные так:

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 для текущего идентификатора, но я просто не вижу, как соединить его с моделью Points, такчто я могу сделать остальную часть запроса (т.е. получить умноженную сумму и имя точки)

enter image description here

  • * Order имеет несколькоOrderPoint предметов.
  • У OrderPoint есть единичный Point элемент.
  • A 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)")
                      }
                  }
          }

1 Ответ

0 голосов
/ 25 мая 2018

Чтобы извлечь все Point s, на которые есть ссылка в OrderPoint s, из Order, вам нужно запросить Point и присоединиться к OrderPoint.Затем вы можете добавить фильтр к OrderPoint, фильтрующему порядок, к которому вы хотите запросить.

Это приведет к следующему свободному запросу:

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

...