チャットモデルのルームエンティティ間の1対多の関係を定義する


8

Roomデータベースの使用を開始し、ルームエンティティを作成するためにいくつかのドキュメントを調べました。これらは私の関係です。チャットチャネルは多くの会話を持つことができます。したがって、これは1対多の関係になります。したがって、以下のようにエンティティを作成しました。

チャネルエンティティ

@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
}

ご覧のとおり、会話チャネルに属しています。ユーザーがチャネルのリストを表示するとき、リストアイテムの最後の会話のいくつかの属性を表示する必要があります。私の質問は、上記のような関係を宣言するだけで十分ですか、またはChannelクラスにConverstionオブジェクトを含める必要がありますか?私がそれを処理できる他の方法は何ですか?UIは、ユーザーがスクロールしたときに、チャネルリストの各アイテムで時間、ステータスなどとともに発生した最新の会話を取得する必要があるためです。したがって、クエリを実行すると、UIに遅れが生じることはありません。

そして、どうすればChannelオブジェクトに最近のConverstaionオブジェクトを含めることができますか?

回答:


1

次のような別のクラスを作成することをお勧めします(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

その後、次のようにdaoで使用します。

 @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>>

上記のようなリレーションを宣言するだけで十分ですか、それともConverstionオブジェクトをChannelクラスに含める必要がありますか?

Roomは会話テーブルにいくつかの列を作成するため、Channelクラスに会話を含めないでください。


0

あなたはシャネルの内側でLastConversationあることができますConversation object。ルームレイヤーからテーブルシャネルを変更して、lastConversationが更新されるたびにこれを更新する必要があります。(更新データベースのパフォーマンスはそれほど高くありません)。シャネルリストのソートを実装する(比較可能)。UIの更新がクールになります。また、UIまたはViewModelからのロジックはより単純です。私もこのようにしました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.