You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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(字符串)

需求

  1. 筛选出adPromote为'reach-up-ad'和'free-ad'的数据,且'reach-up-ad'排在列表最前,之后展示'free-ad'
  2. 分页规则:首次加载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
    }
  }
]);

代码说明

  1. 筛选优化:用$in直接在$match阶段完成广告类型筛选,比前端filter更高效,减少数据传输量
  2. 排序逻辑:通过$cond给不同广告类型设置排序权重,确保'reach-up-ad'始终排在'free-ad'之前,同时保留_id倒序的规则
  3. 字段拼接:用MongoDB原生$concat操作符完成title和condition的拼接,把前端处理逻辑迁移到后端
  4. 分页逻辑:保持$skip和$limit的顺序,确保分页正确性,前端只需传递累计跳过的条目数即可实现加载更多

内容的提问来源于stack exchange,提问作者asela daskon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:52:50