Definir una relación de uno a muchos entre entidades de sala para el modelo de chat

8

Comencé a usar la base de datos de Room y revisé varios documentos para crear entidades de room. Estas son mis relaciones. Un canal de chat puede tener muchas conversaciones. Entonces esto va como una relación de uno a muchos. Por lo tanto, creé entidades como a continuación.

Entidad de canal

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

Entidad de conversación

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

Ahora, como puede ver, la conversación pertenece a un canal . Cuando el usuario ve una lista de canales, necesito mostrar varios atributos de la última conversación en el elemento de la lista. Mi pregunta es, ¿es suficiente si solo declaro una relación como la anterior o si debo contener un objeto de conversación en la clase Channel? ¿Cuáles son las otras formas en que puedo manejarlo? Porque la interfaz de usuario necesita obtener la conversación más reciente que ocurrió junto con el tiempo, el estado, etc. en cada elemento de la lista de canales cuando el usuario se desplaza. Por lo tanto, no debería haber ningún retraso en la interfaz de usuario debido a esto cuando consulto.

¿Y cómo puedo tener un objeto Converstaion reciente en el objeto Channel?

androidbash
fuente

Respuestas:

1

Sugiero crear otra clase (no en DB, solo para mostrar en la interfaz de usuario) como esta:

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
    .
    .
    .
)

Obtenga la última conversación en cada canal mediante esta consulta:

 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

luego úsalo en tu dao así:

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

¿es suficiente si solo declaro una relación como la anterior o debo contener un objeto de conversación en la clase Channel?

No debe contener Conversación en la clase Canal, ya que Room creará algunas columnas para ella en la tabla Conversación.

Iman Hamidi
fuente
0

Puede tener un LastConversationque está Conversation objectdentro del Chanel. Debe actualizar esto cada vez que se actualiza la última Conversación modificando la tabla Chanel desde la capa Habitación. (No requiere tanto rendimiento para la actualización db). Mediante la implementación de la ordenación para la lista Chanel (Comparable). Su actualización de la interfaz de usuario será genial. Y su lógica desde la interfaz de usuario o ViewModel es más simple. Lo hice así también.

Thành Hà Văn
fuente