首页 > 解决方案 > Mongoose:使用自定义函数在查询/聚合中转换值

问题描述

我的产品系列如下所示:

[{
  _id: '1',
  name: 'Car'
  price: {
    currency: 'EUR',
    value: 1200
  }
}, {
  _id: '2',
  name: 'TV'
  price: {
    currency: 'GBP',
    value: 150
  }
}, {
  _id: '3',
  name: 'Phone'
  price: {
    currency: 'USD',
    value: 240
  }
}]

现在,有人向我的后端发送请求以显示价格在 10 到 500 PLN 之间的所有产品。我的想法是获取基础货币 PLN 的当前汇率,计算每种产品货币每次迭代的边缘价格(10 和 500),并查看价格是否在计算范围内。问题是我无法构建正确的查询。我试过这样:

const query = [
    ...(req.query.priceFrom ? [{ "price.value": { "$gte": getCalculatedRange(req.query.priceFrom, '$price.currency') }}] : []),
    ...(req.query.priceTo ? [{ "price.value": {"$lte": getCalculatedRange(req.query.priceTo, '$price.currency') }}] : [])
];

const products = await Product.find({ $and: query });

如您所见,我想获得当前迭代产品价格的正确范围,但问题是不可能(或者可能?)将当前迭代中的值(在我的情况下:货币)传递给函数以进行转换价值。文本 '$price.currency' 被传递给函数,而不是来自对象的实际价值(我知道这在我看来很明显和愚蠢,但我想彻底说明它并清楚我在努力解决的问题)。

有没有办法让它工作?

标签: node.jsmongodbexpressmongoosecurrency

解决方案


通过聚合和组合运算符解决它,例如:

  • $addFields - 用于创建临时字段以保持转换后的价格
  • 用于多种货币情况的嵌套 $switch:

    $switch: {
        branches: [
            {
                case: { $eq: ['eur', '$price.currency'] },
                then: { $multiply: ['$price.value', getRate(req.query.priceUnit.toLowerCase(), 'eur')] },
             }, {
                case: /* next case */
             }
       ],
       default: '$price.value'
    }
    
  • $redact + $cond + $gte / $lte 检查转换后的价格是否在特定范围内(如果是:$$KEEP,否则:$$PRUNE)


推荐阅读