Kotlin开发Facebook克隆应用:如何在Room Entity数据类中定义粉丝与关注列表
数据模型设计优化方案
现有代码的核心问题
- 后端MongoDB的
followers/followings字段当前定义为普通Array,实际应该存储其他用户的ID而非完整用户对象,否则会出现严重的数据冗余,用户信息更新时所有关联的列表都需要同步修改,维护成本极高 - 安卓端Room实体直接定义
Array<User>类型的字段不符合Room规范,Room原生不支持直接存储自定义对象数组,会直接触发编译报错
1. 后端Mongo Schema优化
不用调整整体结构,只要明确数组存储的是ObjectId类型的用户ID即可,还可以通过关联配置简化后续查询:
const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ username:{ type:String, required : true, min:3, max:50, }, email:{ type:String, required:true, unique:true }, password:{ type:String, required : true, }, profilePicture:{ type:String, default:'' }, coverPicture:{ type : String, default:'' }, // 存储关注者的用户ID,关联User集合 followers:{ type:[mongoose.Schema.Types.ObjectId], ref: 'User', default :[] }, // 存储正在关注的用户ID,关联User集合 followings:{ type:[mongoose.Schema.Types.ObjectId], ref: 'User', default:[] }, isAdmin:{ type:Boolean, default : false } }, {timestamps:true} ); const User = mongoose.model('User',userSchema); exports.userSchema = userSchema; exports.User = User;
后续需要查询完整的关注/粉丝列表时,调用populate('followers')即可自动关联查询出完整的用户对象,不需要手动做二次查询。
2. 安卓端Room实体优化
Room不能直接存储用户对象数组,我们调整为存储关注/粉丝的ID列表,搭配TypeConverter做类型转换即可:
第一步:新增类型转换器
class Converters { @TypeConverter fun fromStringList(list: List<String>?): String? { return list?.joinToString(",") } @TypeConverter fun toStringList(data: String?): List<String>? { return data?.split(",")?.takeIf { it.isNotEmpty() } ?: emptyList() } }
第二步:注册转换器到Room数据库
@Database(entities = [User::class], version = 1) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { // 你的DAO定义 }
第三步:修改User实体类
@Entity(tableName="user_table") @Parcelize data class User( @PrimaryKey(autoGenerate = true) val userId : Int=0 , val username :String, val email :String, val password : String, // 存储粉丝的用户ID列表,不再嵌套完整User对象 var followerIds: List<String> = emptyList(), // 存储关注的用户ID列表 var followingIds: List<String> = emptyList(), // 补齐和后端对应的其他字段 val profilePicture: String = "", val coverPicture: String = "", val isAdmin: Boolean = false, val createdAt: Long = 0, val updatedAt: Long = 0 ) : Parcelable data class UserResponse(val user:User?)
如果业务需要在本地缓存完整的关注/粉丝用户信息,单独新增DAO方法根据ID查询对应的用户条目即可,不要嵌套存到User实体中,避免出现数据冗余和一致性问题。
内容的提问来源于stack exchange,提问作者Yellow Clock
相关产品推荐
相关产品推荐

