Объединить несколько объединений с фильтрами в Vapor

#mysql #swift #join #vapor

#mysql #swift #Присоединиться #vapor

Вопрос:

В моем бэкэнде у меня есть Post s и a PostController . Сообщение может быть visibleToFriendOnly .
В GET /posts я хочу вернуть все записи, которые разрешено просматривать текущему пользователю.
У User модели есть friends свойство, которое является стержнем User, User со столбцами userID и friendID .

В настоящее время я получаю сообщения, подобные этому:

 /// /posts
func all(req: Request) throws -> Future<[Post]> {
    let authenticated = try req.requireAuthenticated(User.self)
    return Post.query(on: req)
        .filter(Post.visibleForUserType == authenticated.type)
        // FIXME: respect .visibleForFriendsOnly
        .all()
}
  

У меня возникли трудности с этим, потому что для каждого Post мне пришлось бы получить userID , а затем User (кто является автором), а затем запросить пользователя friends и посмотреть, есть ли текущий пользователь в этом списке.
Есть ли возможный способ сделать это? Может быть, объединение или что-то в этомроде?

Комментарии:

1. Я бы посоветовал попробовать запросить необходимые данные в одном запросе, используя raw query, тогда вы поймете, возможно ли это с Fluent или вам нужно что-то большее

2. Не могли бы вы показать какой-нибудь код? Я относительно новичок в Vapor и во всем, что касается серверной части / базы данных, особенно объединений… @imike

3. вы могли бы найти меня в Discord как имайк #3049

Ответ №1:

Похоже, вы могли бы создать пользовательский необработанный запрос, подобный этому

 return req.requestPooledConnection(to: .mysql).flatMap { conn in
    defer { try? req.releasePooledConnection(conn, to: .mysql) }
    return conn.raw("""
    SELECT posts.* FROM posts
    LEFT OUTER JOIN user_friends
        ON (user_friends.userID = posts.userID AND user_friends.friendID = 3)
        OR (user_friends.friendID = posts.userID AND user_friends.userID = 3)
    GROUP BY posts.id
    HAVING COUNT(user_friends.id) = 2 OR posts.userID = 3 OR visibleForFriendsOnly = 0
    """).all(decoding: Post.self)
}