使用Mongo(ose)从NumberDecimal中提取十进制

时间:2017-01-30 10:51:15

标签: javascript node.js mongodb mongoose mongodb-query

在用于存储货币值的数字模型中,MongoDB docs状态:

  

从mongo shell中使用NumberDecimal()构造函数分配和查询十进制值。

同样,使用Morphia Java库时,BigDecimals会自动插入BigDecimals。

我使用Mongoose查询Node中的Mongo并尝试提取存储为NumberDecimal的字段的数值。但是,这个值奇怪地包含在查询结果中,我不知道如何通过Mongo或Mongoose提取它:

[  
   {  
      "openValue":{  
         "$numberDecimal":"119.931"
      },
      "timestamp":"2017-01-20T10:30:00.000Z"
   },
   {  
      "openValue":{  
         "$numberDecimal":"119.965"
      },
      "timestamp":"2017-01-20T10:31:00.000Z"
   }
]

我在应用程序代码中使用parseFloat()说过的一篇文章将执行我想要的内容,但迭代结果执行此转换效率不高。避免迭代和转换意味着每当我想要它们的值时,就会在NumberDecimals上运行该函数,这会很烦人。

有没有办法可以使用Mongo或Mongoose将上面的JSON查询结果转换成下面的内容?

[  
   {  
      "openValue": 119.931,
      "timestamp":"2017-01-20T10:30:00.000Z"
   },
   {  
      "openValue": 119.965,
      "timestamp":"2017-01-20T10:31:00.000Z"
   },
   {  
      "openValue": 119.975,
      "timestamp":"2017-01-20T10:32:00.000Z"
   }
]

我尝试将字段选为...openValue.$numberDecimal,但这并不起作用。谢谢!

编辑:这是我的Mongoose架构:

var EquityHistoryModel = new Schema({
   _id: {
      equityIdentifier: { type: {
         exchange: { type: String, index: true },
         symbol: { type: String, index: true }
      }, index: true },
      instant: { type: Date, index: true },
      durationMinutes: { type: Number }
   },
   open: { type: mongoose.Schema.Types.Decimal },
   high: { type: mongoose.Schema.Types.Decimal },
   low: { type: mongoose.Schema.Types.Decimal },
   close: { type: mongoose.Schema.Types.Decimal },
   volume: { type: Number },
   isDividendAdjusted: { type: Boolean },
   isSplitAdjusted: { type: Boolean }
}, { collection: 'equityHistories', versionKey: false });

以上是第一个JSON结果的Mongoose查询:

mongo.EquityHistoryModel.aggregate([  
   {  
      "$match":{  
         "_id.equityIdentifier.exchange":passed_in,
         "_id.equityIdentifier.symbol":passed_in,
         "_id.instant":passed_in
      }
   },
   {  
      "$project":{  
         "_id":0,
         "openValue":"$open",
         "timestamp":"$_id.instant"
      }
   }
],

2 个答案:

答案 0 :(得分:1)

您还可以覆盖toJSON方法:

// Never return '__v' field and return the 'price' as String in the JSON representation
// Note that this doesn't effect `toObject`
EquityHistoryModel.set('toJSON', {
  getters: true,
  transform: (doc, ret) => {
    if (ret.price) {
      ret.price = ret.price.toString();
    }
    delete ret.__v;
    return ret;
  },
});

答案 1 :(得分:0)

与我的预期相反,似乎会自动提取值。对结果进行字符串化会自动将值包装在NumberDecimal中。请参阅下面手动输出的代码:

console.log(docs[0].openValue);
119.800
console.log(JSON.stringify(docs[0].openValue]);
{"$numberDecimal":"119.800"}

此外,由于res.json或res.send使用stringify,我努力发送查询结果。相反,我写了一个替换函数并在Node中设置属性。