当前位置: 首页 > news >正文

MongoDB中消息已读未读状态怎么做_时间戳水位线与例外列表

应使用水位线+时间戳方案替代字符串状态字段:status(终态)+ statusUpdatedAt(毫秒时间戳),配合 chat_read_watermarks 独立集合与 chat_message_exceptions 例外表,通过 {receiverId:1,timestamp:-1} 复合索引和 $lt 查询提升性能。用 status 字段做已读/未读标记,但别只存字符串直接在 Message 文档里加 status: "read" 或 "unread" 最简单,但线上出问题时你会发现:状态翻转不幂等、批量标记漏数据、用户撤回消息后状态错乱。根本原因是没区分「状态归属」和「状态生效时间」。正确做法是把状态拆成两个字段:status(当前终态) + statusUpdatedAt(long 类型时间戳)。比如用户 A 给 B 发了 10 条消息,B 在 16:02:33 点开会话,此时不是遍历更新 10 条文档的 status,而是写一条「水位线」记录:{"userId": "B", "chatWith": "A", "lastReadAt": 1741708953000},后续查未读数时用 timestamp < lastReadAt 过滤,再排除掉「例外消息」(比如被撤回、被禁言期间发的)。避免用字符串比较做状态判断(如 status == "read"),MongoDB 的字符串索引效率低于数值索引lastReadAt 必须用毫秒级 long,别用 Date 对象——驱动序列化可能引入时区偏差水位线记录要单独建集合(如 chat_read_watermarks),不要塞进 messages 集合里,否则每次查未读数都要全表扫描find() 查未读数时,为什么 $lt 比 $ne 快得多有人写 { status: { $ne: "read" } } 查未读消息,初看没错,但一上量就卡:MongoDB 无法对字符串枚举字段高效走索引,尤其当 status 还有 "sending"、"failed"、"revoked" 多种值时,$ne 会退化为全索引扫描。而基于水位线的查询是 { senderId: "A", receiverId: "B", timestamp: { $lt: 1741708953000 } },只要在 { receiverId: 1, timestamp: -1 } 上建复合索引,就能用上索引范围扫描,QPS 提升 5–10 倍。索引字段顺序很重要:receiverId 在前用于等值过滤,timestamp 在后用于范围裁剪别忘了加 hint 强制走这个索引,尤其在 MongoDB 4.0+ 多文档事务场景下,优化器有时会选错执行计划如果支持「已读回执」,水位线得按设备维度存(如加 deviceId 字段),不然 iOS 和 Android 同时在线时状态会互相覆盖撤回、禁言、定时消息怎么进「例外列表」水位线解决的是「时间切片」问题,但业务规则会打破时间连续性。比如用户 B 在 16:02:33 看完消息,但 16:02:45 收到一条撤回通知——这条原消息不该算已读;又比如群聊中某人被禁言后发的消息,即使时间戳在水位线之前,也不该计入未读。 腾讯小微 基于微信AI智能对话系统打造的智能语音助手解决方案

http://www.jsqmd.com/news/712986/

相关文章:

  • 抖音批量下载器的技术突破与工程化实践:从手动到自动化的内容采集革命
  • 安徽省CPPM官方报名中心授权机构及联系方式(官方正规报名通道) - 中供国培
  • 物料管理是什么?物料管理的具体工作有哪些?
  • DHCP/DNS/Ensp常见命令
  • 如何高效处理技术文档翻译:BabelDOC智能排版保留完整指南
  • ARM SCTLR2_EL2寄存器解析与虚拟化应用
  • 如何用XUnity.AutoTranslator轻松实现游戏多语言实时翻译:完整新手教程
  • 终极指南:5分钟搞定Windows上的AirPods完整体验,免费开源神器AirPodsDesktop使用教程
  • AI 工程知识图谱:从 Transformer 到 Agentic AI 的全景地图
  • 2026第四届“网安湘军杯”精英挑战赛(网络安全)
  • RWKV-7 (1.5B World)多语言Prompt工程:中英日提示词设计最佳实践
  • Zotero重复文献清理终极指南:5分钟批量合并重复条目的完整教程
  • BabelDOC:智能排版保留的专业PDF翻译工具终极指南
  • 基于深度学习YOLOv8开发的水果成熟度检测系统
  • C++20标准中constexpr支持的全面扩展解析
  • 码力全开特辑直播预告|4月27日16:00,PyPTO IDE可视化工具介绍
  • Android 高级工程师面试参考答案:网络、存储与安全
  • cpp-httplib:如何在现代C++项目中实现零依赖的HTTP/HTTPS通信?
  • 第三届“长城杯”网数智安全大赛(防护赛)总决赛即将开启
  • DUALVISION: RGB-Infrared Multimodal Large Language Models for RobustVisual Reasoning用于鲁棒视觉推理的 RGB-红外
  • 纸巾包装设计公司哪家专业靠谱 生活用纸纸巾品牌包装升级首选哲仕设计 - 设计调研者
  • 分析2026年实验室反应釜贸易商,上海岩征仪器价格如何 - 工业品牌热点
  • 深入解析,什么是Agent,Agent的 架构与设计模式
  • VisualStudio控制台中文乱码解决方案
  • json,一个通用的 Python 库!
  • Voxtral-4B-TTS-2603部署教程:CSDN GPU实例安全组开放7860/8000端口实操
  • 如何快速配置ParsecVDisplay:虚拟显示驱动的终极指南
  • 2026年好用的对接精度高的室外移动机器人品牌有哪些,推荐靠谱厂家 - 工业品牌热点
  • HoRain云--PowerShell核心概念全解析
  • 终极游戏操作优化指南:用Hitboxer解决SOCD冲突,释放你的竞技潜能