MEAN栈约会应用类WhatsApp聊天消息删除功能Schema设计咨询
方案选型结论
优先选择优化后的单条消息存共享属性的方案(基于你提的方案1调整),综合开发成本、维护成本、扩展性都远优于方案2。
原有两个方案的核心问题
- 原方案1的缺陷:单个
action字段存储删除状态的设计扩展性极差,无法支持双方同时单向删除同一条消息的场景,也没法兼容后续点赞、编辑、已读状态等额外字段的扩展。 - 方案2的缺陷:双份会话存储的设计会导致所有消息写操作(编辑、点赞、撤回、状态同步)都需要执行两次,不仅代码冗余度高,还极易出现双写不一致导致的两端消息不同步问题,存储成本也直接翻倍,后期排查问题的成本极高。
优化后的方案1实现逻辑
不用单个action字段,调整为在单条消息文档中新增三个布尔型字段,默认值均为false:
deleted_by_sender:标记发送方是否单向删除该消息deleted_by_receiver:标记接收方是否单向删除该消息delete_for_all:标记是否执行了双方删除操作
对应业务逻辑实现:
- 单向删除:操作用户为发送方时将
deleted_by_sender设为true,为接收方时将deleted_by_receiver设为true;用户拉取消息时直接在MongoDB查询中加过滤条件,符合当前用户删除标记的消息直接过滤不返回。 - DELETE FOR ALL:直接将
delete_for_all设为true,所有用户拉取该消息时都直接过滤。 - 永久擦除:定时任务清理满足
delete_for_all == true或者deleted_by_sender == true AND deleted_by_receiver == true的消息即可,完全符合你的存储清理需求。
该方案的核心优势
- 所有消息公共属性(内容、发送时间、点赞数、编辑状态、已读状态)仅存一份,所有写操作仅需执行一次,不存在双写不一致问题,后续扩展功能的成本极低。
- 查询过滤逻辑简单,性能损耗可以忽略,配合socket.js做实时删除推送时,单向删除仅推给操作方,双方删除推给两个用户即可,逻辑清晰不易出错。
- 存储成本比方案2低50%,后续如果需要扩展群聊场景,仅需将两个删除标记字段调整为
deleted_users数组存储删除用户ID即可,扩展性极强。
实现注意事项
- 消息删除的socket事件要区分类型,单向删除事件不要推送给另一方,避免泄露用户删除消息的操作行为。
- 永久擦除的定时任务无需高频执行,每天跑一次即可,也可以直接用MongoDB的TTL索引实现自动清理。
- 后续如果新增消息编辑、点赞等功能,直接在消息文档上加对应字段即可,所有操作仅需修改一次记录,无需处理多份数据同步问题。
内容的提问来源于stack exchange,提问作者Izuna894
相关产品推荐
相关产品推荐

