0

0

MongoDB 聚合查询中按用户点赞顺序(数组索引)正确分页与排序的完整实现

碧海醫心

碧海醫心

发布时间:2026-02-07 11:34:05

|

722人浏览过

|

来源于php中文网

原创

MongoDB 聚合查询中按用户点赞顺序(数组索引)正确分页与排序的完整实现

本文详解如何在 mongodb 聚合管道中精准保留 `likedvideos` 数组原始插入顺序(即最新点赞排第一),并支持 `skip`/`limit` 分页,避免 `$lookup` + `$unwind` 后顺序错乱问题。

在使用 MongoDB 实现「用户点赞视频列表」功能时,一个常见但易被忽视的关键点是:$lookup 关联后默认不保留原始数组顺序。由于 likedVideos 是按时间追加的 ObjectId 数组(如 [video_1, video_2, video_3],其中 video_3 为最新),前端要求「最新点赞优先展示 + 支持懒加载分页」,这就要求聚合结果必须严格按该数组的逆序索引(从末尾到开头)排序,而非文档自然顺序或 _id 时间顺序。

原始代码的问题根源在于:

  • $unwind 后立即 $group + $push 无法还原原始位置信息;
  • $slice 在 $project 阶段截取的是 $lookup 返回的无序数组(BSON 数组本身无稳定顺序保证,尤其跨集合关联后);
  • 缺少显式排序逻辑,导致 skip/limit 应用于错误顺序的数据流。

✅ 正确解法是:在 $unwind 后,利用 $indexOfArray 动态计算每个视频在原始 likedVideos 数组中的索引位置,再按该索引倒序排序,最后分页。以下是优化后的完整聚合管道(已适配 Mongoose 和标准 MongoDB Driver):

const { userId, skip = 0, limit = 10 } = req.query;
const pipeline = [
  { $match: { _id: new mongoose.Types.ObjectId(userId) } },
  {
    $lookup: {
      from: "videos",
      localField: "likedVideos", // 注意字段名一致性(原文案中为 liked_videos,实际应与 Schema 一致)
      foreignField: "_id",
      as: "likedVideos"
    }
  },
  {
    $unwind: {
      path: "$likedVideos",
      preserveNullAndEmptyArrays: true // 确保用户未点赞时返回空数组而非报错
    }
  },
  {
    $addFields: {
      likedIndex: {
        $indexOfArray: ["$likedVideos", "$likedVideos._id"] // ✅ 关键:获取当前视频在原始 likedVideos 数组中的位置
      }
    }
  },
  { $sort: { likedIndex: -1 } }, // 降序 → 最新点赞(索引最大)排最前
  { $skip: parseInt(skip) },
  { $limit: parseInt(limit) },
  { $replaceRoot: { newRoot: "$likedVideos" } } // 将视频文档提升为根对象,输出干净数组
];

const result = await User.aggregate(pipeline).toArray();
res.status(200).json(result);

? 关键要点说明

Ribbet.ai
Ribbet.ai

免费在线AI图片处理编辑

下载
  • preserveNullAndEmptyArrays: true 防止用户 likedVideos 为空时管道中断;
  • $indexOfArray 的第一个参数必须是原始数组字段("$likedVideos"),第二个参数是当前 unwind 出的文档 _id("$likedVideos._id"),二者类型需严格匹配(均为 ObjectId);
  • 排序必须在 $skip/$limit 之前执行,否则分页将作用于未排序数据;
  • $replaceRoot 确保最终响应是纯视频文档数组(如 [{_id: ..., videoUrl: ...}, ...]),而非嵌套结构。

⚠️ 注意事项

  • 若 likedVideos 字段名在 Schema 中为 liked_videos(下划线命名),请同步修正 $lookup.localField 和 $indexOfArray 的第一个参数;
  • skip/limit 值务必校验为非负整数,建议添加中间件防护(如 Math.max(0, parseInt(skip)));
  • 对于高并发点赞场景,该方案性能良好($indexOfArray 为 O(n) 但 n 通常 ≤ 数千),若需极致性能(如百万级点赞),可考虑冗余存储 likedAt 时间戳并建复合索引。

此方案兼顾语义清晰性、执行可靠性与分页准确性,是处理「数组顺序依赖型关联查询」的标准实践。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

179

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

222

2025.12.18

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

282

2023.07.18

mongodb启动命令
mongodb启动命令

MongoDB 是一种开源的、基于文档的 NoSQL 数据库管理系统。本专题提供mongodb启动命令的文章,希望可以帮到大家。

260

2023.08.08

MongoDB删除数据的方法
MongoDB删除数据的方法

MongoDB删除数据的方法有删除集合中的文档、删除整个集合、删除数据库和删除指定字段等。本专题为大家提供MongoDB相关的文章、下载、课程内容,供大家免费下载体验。

160

2023.09.19

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

986

2023.11.02

mongodb有哪些应用领域
mongodb有哪些应用领域

mongodb 的应用领域涵盖广泛,包括内容管理系统、社交媒体、分析、移动应用、物联网、金融科技、医疗保健和广告技术等领域,因其灵活性、可扩展性和易用性而广受欢迎。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

337

2024.04.02

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

493

2024.04.02

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

2

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.9万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号