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

FeatherJS Get请求Before Hook实现MongoDB聚合排序问询

FeatherJS + MongoDB Find操作Before Hook实现自定义分组排序

需求实现思路

要实现「先按price是否为0分组,每组内按expirydate升序,付费组在前」的排序,普通MongoDB sort无法直接完成,需要通过聚合管道实现。我们可以在FeatherJS的find操作Before Hook中替换查询逻辑为聚合管道,达成需求。

示例数据与预期结果

输入数据

[
  { name: "菜A", price: 20, expirydate: new Date("2024-10-05") },
  { name: "菜B", price: 0, expirydate: new Date("2024-10-01") },
  { name: "菜C", price: 15, expirydate: new Date("2024-10-03") },
  { name: "菜D", price: 0, expirydate: new Date("2024-10-02") },
  { name: "菜E", price: 30, expirydate: new Date("2024-10-04") }
]

预期输出

[
  { name: "菜C", price: 15, expirydate: new Date("2024-10-03") },
  { name: "菜E", price: 30, expirydate: new Date("2024-10-04") },
  { name: "菜A", price: 20, expirydate: new Date("2024-10-05") },
  { name: "菜B", price: 0, expirydate: new Date("2024-10-01") },
  { name: "菜D", price: 0, expirydate: new Date("2024-10-02") }
]

完整Hook代码实现

在你的菜品服务钩子文件(如src/services/dishes/dishes.hooks.js)中添加以下逻辑:

const { HookContext } = require('@feathersjs/feathers');

// 自定义排序Hook
const sortDishesByPriceAndExpiry = async (context) => {
  // 构建聚合管道
  const pipeline = [
    // 1. 添加临时字段标记是否为付费菜品
    {
      $addFields: {
        isPaid: { $ne: ["$price", 0] }
      }
    },
    // 2. 排序:先按付费标记降序(付费组在前),再按过期时间升序
    {
      $sort: {
        isPaid: -1,
        expirydate: 1
      }
    },
    // 3. 移除临时字段,返回原始数据结构
    {
      $project: {
        isPaid: 0
      }
    }
  ];

  // 保留原查询过滤条件(如果有)
  if (Object.keys(context.params.query).length > 0) {
    pipeline.unshift({ $match: context.params.query });
  }

  // 替换为聚合查询
  context.params.pipeline = pipeline;
  context.params.query = {}; // 清空原查询,避免冲突

  return context;
};

// 注册Hook到find操作的Before阶段
module.exports = {
  before: {
    all: [],
    find: [sortDishesByPriceAndExpiry], // 加入自定义排序Hook
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },
  // 其他Hook配置...
};

代码说明

  1. 聚合管道逻辑:
    • $addFields:添加临时字段isPaid,值为price≠0的布尔值,作为分组排序的依据
    • $sort:先按isPaid降序(true在前,对应price≠0的组),再按expirydate升序实现组内排序
    • $project:移除临时字段,保证返回数据结构与原请求一致
  2. 兼容原查询条件:如果用户原本的find请求带有过滤参数(如?name=菜A),会自动添加$match阶段保留过滤逻辑
  3. FeatherJS适配:MongoDB适配器会优先使用params.pipeline执行聚合查询,替代默认的find操作,完美适配FeatherJS的Hook机制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:23:09