2

我正在尝试查询与两个用户的聊天。如果它存在,我想退货。如果不是,我想与这两个用户创建新的聊天并将其返回。

如果聊天存在,评论会显示失败的地方。

如果您可以展示如何在这种情况下与这两个用户创建新的聊天,也会很有帮助。

func create(req: Request) throws -> EventLoopFuture<Chat> {
  
  let currentUser = try req.auth.require(User.self)
  
  guard
    let userID = req.parameters.get("userID"),
    let uuid = UUID(userID)
  else { throw Abort(.badRequest) }
  
  return User
    .query(on: req.db)
    .filter(\.$id == uuid)
    .with(\.$chats)
    .first()
    .unwrap(or: Abort(.internalServerError))
    .flatMap({ chatUser -> EventLoopFuture<Chat> in
      
      let chat = chatUser
        .chats
        .filter({
          $0.users.contains(where: { $0.id == currentUser.id }) // FAILS HERE: Fatal error: Siblings relation not eager loaded, use $ prefix to access: Siblings<Chat, User, ChatUser>(from: [chat_id], to: [user_id]): file
        })
        .first
      
      if let chat = chat {
        
        return req
          .eventLoop
          .makeSucceededFuture(chat)
        
      } else {
        
        // create new chat with those two users and return
        
      }
    })
}

简化模型:

final class Chat: Model, Content {
  @ID(key: .id)
  var id: UUID?
  
  @Siblings(through: ChatUser.self, from: \.$chat, to: \.$user)
  var users: [User]
}

final class User: Model, Content {
  @ID(key: .id)
  var id: UUID?
  
  @Siblings(through: ChatUser.self, from: \.$user, to: \.$chat)
  var chats: [Chat]
}

final class ChatUser: Model {
  @ID(key: .id)
  var id: UUID?

  @Parent(key: Keys.chatId)
  var chat: Chat

  @Parent(key: Keys.userId)
  var user: User
}
4

2 回答 2

3

0xTim 在 Discord 上帮助了我。在阅读此文档后,我设法使其工作

这是工作解决方案:

func create(req: Request) throws -> EventLoopFuture<Chat> {
  
  let currentUser = try req.auth.require(User.self)
  
  guard
    let userID = req.parameters.get("userID"),
    let userUUID = UUID(userID)
    else { throw Abort(.badRequest) }
  
  return User
    .query(on: req.db)
    .filter(\.$id == userUUID)
    .with(\.$chats, { chats in
      chats.with(\.$users)
    })
    .first()
    .unwrap(or: Abort(.internalServerError))
    .flatMap({ chatUser -> EventLoopFuture<Chat> in
      
      let chat = chatUser
        .chats
        .filter({
          $0.users.contains(where: { $0.id! == currentUser.id! })
        })
        .first
      
      if let chat = chat {
        
        return req.eventLoop.makeSucceededFuture(chat)
        
      } else {
        
        let newChat = Chat()
        return newChat
          .save(on: req.db)
          .flatMap({
            
            newChat
              .$users
              .attach([chatUser, currentUser], on: req.db)
              .flatMap({
                
                return req.eventLoop.makeSucceededFuture(newChat)
              })
          })
      }
    })
}
于 2020-06-12T02:41:58.100 回答
1

您的问题是,本质上您需要对User模型中使用的模型进行进一步的急切加载ChatUser。如果可能的话,在你的第一个查询中,.with(\.$chats)你会做类似的事情.with(\.$chats.$chats),但这是不可能的。

在这种情况下,与其直接回答您的问题,我可以建议您考虑从查询开始ChatUser吗?如果您在其中寻找Model匹配的记录,然后相应地工作。就像是:

ChatUser.query(on:req.db).filter(\.$id == currentUser.id).filter(\.$chat == userId).first().map { mayExist in
    if let doesExist = mayExist {
        // work with existing chat
    } else {
        // does not exist so create a new one
        // how, depends on your init for the model
        let newChat = ChatUser( user:currentUser.id!, chat:userId)
        newChat.create(on:req.db).map{
            // do something here
        }
    }
}

PS - 赶着去上班,所以这可能是漏洞百出!

于 2020-06-09T06:27:07.520 回答