当前位置: 首页 > 知识库问答 >
问题:

为聊天模型定义房间实体之间的一对多关系

孟杰
2023-03-14

我开始使用Room数据库并通过几个文档来创建房间实体。这些是我的关系。聊天频道可以有很多对话。所以这是一对多的关系。因此我创建了如下实体。

渠道实体

@Entity(primaryKeys = ["channelId"])
@TypeConverters(TypeConverters::class)
data class Channel(
    @field:SerializedName("channelId")
    val channelId: String,
    @field:SerializedName("channelName")
    val channelName: String,
    @field:SerializedName("createdBy")
    val creationTs: String,
    @field:SerializedName("creationTs")
    val createdBy: String,
    @field:SerializedName("members")
    val members: List<String>,
    @field:SerializedName("favMembers")
    val favMembers: List<String>
) {
  // Does not show up in the response but set in post processing.
  var isOneToOneChat: Boolean = false
  var isChatBot: Boolean = false
}

会话实体

@Entity(primaryKeys = ["msgId"],
    foreignKeys = [
        ForeignKey(entity = Channel::class,
                parentColumns = arrayOf("channelId"),
                childColumns = arrayOf("msgId"),
                onUpdate = CASCADE,
                onDelete = CASCADE
        )
    ])
@TypeConverters(TypeConverters::class)
data class Conversation(

    @field:SerializedName("msgId")
    val msgId: String,
    @field:SerializedName("employeeID")
    val employeeID: String,
    @field:SerializedName("channelId")
    val channelId: String,
    @field:SerializedName("channelName")
    val channelName: String,
    @field:SerializedName("sender")
    val sender: String,
    @field:SerializedName("sentAt")
    val sentAt: String,
    @field:SerializedName("senderName")
    val senderName: String,
    @field:SerializedName("status")
    val status: String,
    @field:SerializedName("msgType")
    val msgType: String,
    @field:SerializedName("type")
    val panicType: String?,
    @field:SerializedName("message")
    val message: List<Message>,
    @field:SerializedName("deliveredTo")
    val delivered: List<Delivered>?,
    @field:SerializedName("readBy")
    val read: List<Read>?

) {

data class Message(
        @field:SerializedName("txt")
        val txt: String,
        @field:SerializedName("lang")
        val lang: String,
        @field:SerializedName("trans")
        val trans: String
)

data class Delivered(
        @field:SerializedName("employeeID")
        val employeeID: String,
        @field:SerializedName("date")
        val date: String
)

data class Read(
        @field:SerializedName("employeeID")
        val employeeID: String,
        @field:SerializedName("date")
        val date: String
)

    // Does not show up in the response but set in post processing.
    var isHeaderView: Boolean = false
}

现在,您可以看到,对话属于一个频道。当用户看到频道列表时,我需要在列表项中显示上次对话的几个属性。我的问题是,如果我只是像上面那样声明关系,或者应该在通道类中包含会话对象,这就足够了吗?我还有什么其他方法可以处理它?因为当用户滚动时,UI需要在频道列表的每个项目中获取最近发生的对话以及时间、状态等。因此,当我查询时,UI中不应该有任何延迟。

我怎么能在通道对象中有最近的Converstaion对象?

共有2个答案

商迪
2023-03-14

您可以有一个LastConversation,它是Chanel内部的Conversation对象。每次更新lastConversation时,您都必须通过修改Room层中的表Chanel来更新它。(更新db不需要那么多性能)。通过实现Chanel列表的排序(可比)。您的UI更新会很酷。并且您来自UI或ViewModel的逻辑更简单。我也是这样做的。

高兴贤
2023-03-14

我建议创建另一个类(不是在DB中,只是为了在UI中显示),如下所示:

data class LastConversationInChannel(
    val channelId: String,
    val channelName: String,
    val creationTs: String,
    val createdBy: String,
    val msgId: String,
    val employeeID: String,
    val sender: String,
    val sentAt: String,
    val senderName: String
    .
    .
    .
)

通过以下查询获取每个频道中的最后一次对话:

 SELECT Channel.*
 ,IFNULL(LastConversation.msgId,'') msgId
 ,IFNULL(LastConversation.sender,'') sender
 ,IFNULL(LastConversation.employeeID,'') employeeID
 ,IFNULL(LastConversation.sentAt,'') sentAt
 ,IFNULL(LastConversation.senderName,'') senderName
 from Channel left join 
 (SELECT * from Conversation a  
 WHERE a.msgId IN ( SELECT b.msgId  FROM Conversation AS b 
                    WHERE a.channelId = b.channelId 
                    ORDER BY b.sentAt DESC  LIMIT 1 )) as LastConversation
 on Channel.channelId = LastConversation.channelId

然后像这样在你的刀里使用它:

 @Query(" SELECT Channel.*\n" +
            " ,IFNULL(LastConversation.msgId,'') msgId\n" +
            " ,IFNULL(LastConversation.sender,'') sender\n" +
            " ,IFNULL(LastConversation.employeeID,'') employeeID\n" +
            " ,IFNULL(LastConversation.sentAt,'') sentAt\n" +
            " ,IFNULL(LastConversation.senderName,'') senderName\n" +
            " from Channel left join \n" +
            " (SELECT * from Conversation a  \n" +
            " WHERE a.msgId IN ( SELECT b.msgId  FROM Conversation AS b \n" +
            "                    WHERE a.channelId = b.channelId \n" +
            "                    ORDER BY b.sentAt DESC  LIMIT 1 )) as LastConversation\n" +
            " on Channel.channelId = LastConversation.channelId")
    fun getLastConversationInChannel(): LiveData<List<LastConversationInChannel>>

如果我只是像上面那样声明关系,或者我应该在Channel类中包含Converstion对象,这就足够了吗?

不应在频道类中包含“对话”,因为“房间”将在“对话”表中为其创建一些列。

 类似资料:
  • 问题内容: 我正在寻找一个支持多个房间的websocket / node.js聊天实现。 我还将编写一个需要多个房间或服务器的应用程序,而我只是在寻找一些人们如何操作的代码示例。 谢谢。 我知道有一个提供此服务的服务http://pusherapp.com,但我正在寻找一个开源示例。 问题答案: 我意识到您尚未收到针对您问题的解决方案。建议在我提供答案的地方看这个问题: node-websocke

  • 本文向大家介绍Nodejs实现多房间简易聊天室功能,包括了Nodejs实现多房间简易聊天室功能的使用技巧和注意事项,需要的朋友参考一下 1、前端界面代码   前端不是重点,够用就行,下面是前端界面,具体代码可到github下载。 2、服务器端搭建   本服务器需要提供两个功能:http服务和websocket服务,由于node的事件驱动机制,可将两种服务搭建在同一个端口下。   1、包描述文件:p

  • 我在房间使用关系中添加了一对多关系。我引用这篇文章是为了编写以下房间关系代码。 这篇文章讲述了如何从数据库中读取值,但将实体存储到数据库中会导致用户ID为空,这意味着这两个表之间没有关系。 我不确定在具有用户ID值的情况下,将用户和宠物列表插入数据库的理想方法是什么。 1)用户实体: 2) 宠物实体: 3)用户带宠物POJO: 现在,为了从DB中获取记录,我们使用以下DAO: 编辑 我已创建此问题

  • 我很难找到数据库中多对多关系的最佳设计。我的项目允许用户创建我们所说的日志警报。日志警报将检查给定的日志是否满足某些标准,如果满足,它将向AWS SNS主题发送消息。我想做的是将日志警报与AWS SNS主题联系起来。我还想将哪个用户分配日志警报与AWS SNS主题联系起来。

  • 我很难模拟这种情况。我在设计一个基于位置的优惠券系统。用户可以定义区域和优惠,然后将每个优惠关联到多个区域。此外,每个区域可以有多个优惠。所以zone和offer有很多对很多的关系。用户实体拥有这两个实体。只有在同一用户拥有区域和优惠的情况下,才能将它们关联起来。图表会很有帮助。多谢了。

  • 如何为这种多对多关系分配默认值?制作两个关联表->一个用于收件箱-关系,另一个用于发件箱-关系会更好吗?我该如何做到这一点?这个问题的其他解决方案? 任何帮助都非常感谢--非常感谢!