【问题标题】:Get max of virtual field of each type of record获取每种记录的最大虚拟字段
【发布时间】:2017-10-24 16:44:35
【问题描述】:

我正在将 MongoDB 与猫鼬一起使用。我有一个订单集合,每个订单都有货币(usd、eur、ils 等)和百分比。

我的节点应用程序从另一个服务读取一个值,并且我的 Order 集合有一个名为 price 的虚拟字段,该字段是根据该值和订单文档的百分比计算得出的。

import mongoose, { Schema } from 'mongoose';
import { priceValue } from '../services/price-value';

const orderSchema = new Schema({
    currency: {
        type: 'String',
        required: true
    },
    percent: {
        type: 'Number',
        required: true
    }
}, {
    toObject: {
        virtuals: true
    },
    toJSON: {
        virtuals: true
    }
});

orderSchema.virtual('price').get(function() {
    return priceValue * this.percent;
});

export default mongoose.model('Order', orderSchema);

我需要找到每种货币的最高价格。类似,对于每个 CURRENCY 调用:

db.orders.find({ currency: CURRENCY }).sort({percent: -1}).limit(1);

在节点应用程序中收集结果并计算虚拟价格字段。
但这感觉不正确。正确的做法是什么?

【问题讨论】:

  • priceValue 是否意味着function?或者它只是一个常数值?如果它是一个函数,它缺少(),并且您需要迭代一个“游标”(尽管是一个聚合游标)结果才能应用。但如果它是一个“常数”,那么您可以简单地将值提供给必要的聚合管道并进行计算。
  • @NeilLunn priceValue 是一个值。如何将值提供给必要的聚合管道?我试图避免重复虚拟字段背后的逻辑。

标签: node.js mongodb mongoose aggregation-framework


【解决方案1】:

您可以将其委托给聚合框架,而不是使用“虚拟字段”,这比查询每个可能的“货币”值要好得多。

如果priceValue 是一个简单的“常量”值,那么您只需将其提供给管道表达式即可:

db.orders.aggregate([
  { "$sort": { "currency": 1, "percent": -1 } }, 
  { "$group": {
    "_id": "$currency",
    "percent": { 
      "$first": { 
        "$multiply": [ 
          { "$divide": [ "$percent", 100 ] },
          priceValue
        ] 
      }
    }
  }}
])

所以你$sort 保持“货币”的顺序,并按该“货币”中的每个“百分比”递减。然后你 $group 在每个不同的“货币”上,从每个分组边界获取 $first

然后您需要做的就是将$multiply 应用于priceValue 常量的返回值,从$divide 之后的“百分比”值100,因为您需要实际存储的整个值的除数.

您还应该注意,从聚合管道返回的文档与使用的模型没有相同的架构附加方法。基本原因是您通常会“更改返回文档的形状”,因此“模式”不再适用。

【讨论】:

    【解决方案2】:

    根据this answer,你需要聚合,这是对数据库的一次调用

    db.orders.aggregate([
        { "$sort": { "currency": 1, "percent": -1 } }, // or "percent": 1
        { "$group": {
            "_id": "$currency",
            "percent": { "$first": "$percent" }
        }}
    ])
    

    结果应该类似于,按最大百分比排序并按货币唯一分组

    [{_id: 'usd', percent: 12}, {_id: 'eur', percent: 34}]
    

    然后你可以使用你的

    import { priceValue } from '../services/price-value';
    

    获取价格

    【讨论】:

    • 这种解决方案的一个问题,不是使用虚拟字段实现,我必须复制逻辑并在这个查询结果上重新计算。
    猜你喜欢
    • 2021-08-14
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2015-04-13
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多