如果您有大量文档,您应该使用 DB 服务器而不是 JS 来完成工作。
您没有说您是直接使用猫鼬还是节点驱动程序。我假设您使用的是猫鼬,因为这是大多数人的方式。
所以你的模型是:
// models/stocks.js
const mongoose = require("mongoose");
const conn = mongoose.createConnection('mongodb://localhost/stocksdb');
const StockSchema = new mongoose.Schema(
{
price: Number,
code: String,
date: Date,
},
{ timestamps: true }
);
module.exports = conn.model("Stock", StockSchema, "stocks");
您正确地建议聚合框架将是一个很好的方法。首先,如果我们要处理日期范围之间的返回值,那么数据库中的记录需要是日期对象。从您的示例文档中,您可能已经放置了字符串。插入带有日期的对象的示例是:
db.stocks.insertMany([{code:'0001',price:0.10,date:ISODate('2014-07-04T00:00:00.000Z')}, {code:'0001',price:0.12,date:ISODate('2014-07-05T00:00:00.000Z')},{code:'0001',price:0.13,date:ISODate('2014-07-06T00:00:00.000Z')}, {code:'0001',price:0.12,date:ISODate('2014-07-07T00:00:00.000Z')}])
聚合管道函数接受具有一个或多个管道阶段的数组。
我们应该使用的第一个管道阶段是$match$ match docs,这会将文档过滤到仅我们感兴趣的对性能很重要的记录
{ $match: {
date: {
$gte: new Date('2014-07-03'),
$lte: new Date('2014-07-07')
}
}
}
此阶段将仅将 2014 年 7 月 3 日至 7 日(含)的文档发送到下一阶段(在本例中为所有示例文档)
下一阶段是您可以获得平均值的阶段。我们需要根据一个字段、多个字段或所有字段将值组合在一起。
由于您没有指定要平均的字段,因此我将为所有字段举一个示例。为此,我们使用$group对象$group docs
{
$group: {
_id: null,
average: {
$avg: '$price'
}
}
}
这将获取所有文件并显示所有价格的平均值。
对于您的示例文档,这会导致
{ _id: null, avg: 0.1175 }
检查答案:
(0.10 + 0.12 + 0.12 + 0.13) / 4 = 0.1175
仅供参考:我不会依赖使用 javascript 完成的任何关键计算,例如使用浮点数的数字。如果您对此感到担心,请参阅https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html了解更多详细信息。
为了完整起见,这里是完整的聚合查询
const Stock = require("./models/stocks");
Stock.aggregate([{ $match: {
date: {
$gte: new Date('2014-07-03'),
$lte: new Date('2014-07-07')
}
}},
{
$group: {
_id: null,
avg: {
$avg: '$price'
}
}
}])
.then(console.log)
.catch(error => console.error(error))