如何将React前端MongoDB数据筛选排序逻辑迁移至Mongoose后端?
问题:前端筛选排序逻辑迁移到Mongoose聚合查询报错,需实现指定筛选排序分页需求
报错信息
"error": "MongoServerError: Invalid $addFields :: caused by :: Unrecognized expression '$con'"
前端原有筛选排序代码
try { const { data } = await getMobilePosts(skip); const filterData = await data?.filter(obj => obj.adPromote == "free-ad" || obj.adPromote == "reach-up-ad") .sort((f,p)=>{ if (f.adPromote === 'reach-up-ad' && p.adPromote !== 'reach-up-ad') { return -1; } else if (f.adPromote !== 'reach-up-ad' && p.adPromote === 'reach-up-ad') { return 1; } return 0; }) .map(obj => { return { ...obj, title: `${obj.title} (${obj.features.condition})` } }); setPost([...post, ...filterData]); setSkip(filterData.length); } catch (err) { console.log(err) }
已尝试的后端聚合查询代码
Post.aggregate([ { $match: { $and: [ { expiredAt: {$gte: currentDate} }, { "status": "live" } ] } }, { "$addFields": { "adpromoTypes": { "$con": { "if": { "$and": { "adPromote": { "$eq": 'reach-up-ad' }, } } } } } }, { $sort: { "_id": -1, "adpromoTypes": -1 } }, { "$skip": skip }, { "$limit": PER_REQUEST }, { $project: { "title": 1, } } ]);
集合字段说明
POST集合文档包含字段:
- title(字符串)
- adPromote(字符串,可选值:'reach-up-ad'、'free-ad'、'urgent-ad')
- expiredAt(日期)
- status(字符串)
需求
- 筛选出
adPromote为'reach-up-ad'和'free-ad'的数据,且'reach-up-ad'排在列表最前,之后展示'free-ad' - 分页规则:首次加载5条(优先'reach-up-ad'),后续每次跳过已加载的数量,加载下5条(仍优先剩余的'reach-up-ad',再加载'free-ad')
修复后的正确聚合查询代码
错误原因分析
报错是因为使用了MongoDB不存在的$con表达式,正确的条件判断操作符是$cond。同时需要调整筛选、排序、字段拼接逻辑,完全匹配前端原有行为。
const PER_REQUEST = 5; // 每页固定5条,可根据实际需求调整 Post.aggregate([ // 1. 筛选符合条件的文档:过期时间未到、状态为live、广告类型为目标值 { $match: { expiredAt: { $gte: currentDate }, status: "live", adPromote: { $in: ["reach-up-ad", "free-ad"] } } }, // 2. 添加排序权重:给reach-up-ad设更高优先级(权重值越小越靠前) { $addFields: { sortPriority: { $cond: { if: { $eq: ["$adPromote", "reach-up-ad"] }, then: 1, else: 2 } } } }, // 3. 按权重排序,再按_id倒序(和前端排序逻辑对齐) { $sort: { sortPriority: 1, _id: -1 } }, // 4. 分页处理:跳过已加载数量,取当前页数据 { $skip: skip }, { $limit: PER_REQUEST }, // 5. 拼接title字段:替代前端map的字符串拼接操作 { $project: { title: { $concat: ["$title", " (", "$features.condition", ")"] }, // 如需返回其他字段,在此添加,比如: adPromote: 1, features: 1, expiredAt: 1, status: 1 } } ]);
代码说明
- 筛选优化:用
$in直接在$match阶段完成广告类型筛选,比前端filter更高效,减少数据传输量 - 排序逻辑:通过
$cond给不同广告类型设置排序权重,确保'reach-up-ad'始终排在'free-ad'之前,同时保留_id倒序的规则 - 字段拼接:用MongoDB原生
$concat操作符完成title和condition的拼接,把前端处理逻辑迁移到后端 - 分页逻辑:保持
$skip和$limit的顺序,确保分页正确性,前端只需传递累计跳过的条目数即可实现加载更多
内容的提问来源于stack exchange,提问作者asela daskon
相关产品推荐
相关产品推荐

