javascript - 在 MongoDB 聚合和 NodeJS 中计算过去 200 天的平均值
问题描述
我有一个脚本,它正在计算Volume
我的 MongoDB 中每个集合的平均数据。但由于我有超过 1000 天的记录,我希望计算Average Volume
过去 200 天的唯一记录。
目前我的脚本正在收集正在收集的全部数据(1000 天+)。
目标:我如何设置过去 200 天的范围来计算Volume
它们的平均值。还有一件很重要的事,就是隔天我还想只用最后 200 天。
平均聚合框架
const saveToDatebase = async(symbol, BTCdata) => {
try {
const url = 'mongodb://username:passwprd@ipaddress/port?retryWrites=true&w=majority';
let dateTime = getDateTime();
let db = await MongoClient.connect(url, { useUnifiedTopology: true });
const dbo = db.db('Crypto');
const myobj = Object.assign({ Name: symbol, Date: dateTime }, BTCdata[0]);
await dbo.collection(symbol).insertOne(myobj);
const average = await dbo.collection(symbol).aggregate([{
'$group': {
_id:null,
'Volume': {
'$avg': '$Volume'
}
}
}]).toArray();
console.log('1 document inserted');
console.log(average);
db.close();
} catch (e) {
console.error(e)
}
};
EDIT1 像这样编辑代码后>>
const average = await dbo.collection(symbol).aggregate([{
$match: {
$gte: ["$dateTime", { $subtract: ["$$NOW", 200 * 60 * 60 * 24 * 1000] }]
},
"$group": {
_id: null,
"Volume": {
"$avg": "$Volume"
}
}
}]).toArray();
我收到此错误 >MongoError: A pipeline stage specification object must contain exactly one field.
EDIT2
代码在获得如下代码后,我收到此错误 -MongoError: unknown top level operator: $gte
const average = await dbo.collection(symbol).aggregate([{
$match: { $gte: ["$dateTime", { $subtract: ["$$NOW", 200 * 60 * 60 * 24 * 1000] }] }
},
{
"$group": {
_id: null,
"Volume": {
"$avg": "$Volume"
}
}
}
])
这是文档在 MongoDB 中的样子。
EDIT3
这是我的代码关于最后一次改进的样子。代码是唯一的问题它没有返回我的平均水平。在我的终端中,我收到一个空数组[]
,但没有收到任何错误。我认为问题就在这里 -"$dateTime"
我认为对它的查询是错误的。因为我也试图在 MongoDB Compass 中实现它。也不行。
代码在这里
const average = await dbo.collection(symbol).aggregate([{
$match: {
$expr: {
$gte: [
"$dateTime",
{
$subtract: [
"$$NOW",
200 * 60 * 60 * 24 * 1000
]
}
]
}
}
},
{
"$group": {
_id: null,
"Volume": {
"$avg": "$Volume"
}
}
}
]).toArray();
编辑4
现在我收到一个空数组的唯一问题>[]
我收到一个空数组,原因Date
是保存为string
MongoDB,但要使聚合框架工作,我需要将其存储为object
.
在下面的代码中,有我创建 Date 函数的方法,它将它保存在 MongoDB 中,因为string
我可以更改它以将其保存为object
const getDateTime = () => {
let today = new Date();
let date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
return date + ' ' + time;
};
const saveToDatebase = async(symbol, BTCdata) => {
try {
const url = 'mongodb://username:password@ipadress/port?dbname?retryWrites=true&w=majority';
let dateTime = getDateTime();
let db = await MongoClient.connect(url, { useUnifiedTopology: true });
const dbo = db.db('Crypto');
const myobj = Object.assign({ Name: symbol, Date: dateTime }, BTCdata[0]);
await dbo.collection(symbol).insertOne(myobj);
const average = await dbo.collection(symbol).aggregate([{
'$match': {
'dateTime': { '$gte': new Date((new Date().getTime() - (7 * 24 * 60 * 60 * 1000))) }
},
},
{
'$group': {
_id: null,
'Volume': { '$avg': '$Volume' }
},
}
]).toArray();
console.log('1 document inserted');
console.log(average);
db.close();
} catch (e) {
console.error(e)
}
};
来自 MongoDB 的文档作为文本:
{
"_id": {
"$oid": "5f158c9d80d84408f6c38d8b"
},
"Name": "ADABTC",
"Date": "2020-7-20 13:22:53",
"Open": 0.0000133,
"High": 0.0000133,
"Low": 0.00001325,
"Close": 0.00001326,
"Volume": 1189734,
"Timespan": 30
}
解决方案
您必须在对文档进行分组之前对其进行过滤。应该是这样的:
db.collection.aggregate([
{
$addFields: {
DateObj: {
$regexFindAll: { input: "$Date", regex: "\\d+" }
}
}
},
{
$set: {
DateObj: {
$dateFromParts: {
year: { $toInt: { $arrayElemAt: ["$DateObj.match", 0] } },
month: { $toInt: { $arrayElemAt: ["$DateObj.match", 1] } },
day: { $toInt: { $arrayElemAt: ["$DateObj.match", 2] } },
hour: { $toInt: { $arrayElemAt: ["$DateObj.match", 3] } },
minute: { $toInt: { $arrayElemAt: ["$DateObj.match", 4] } },
second: { $toInt: { $arrayElemAt: ["$DateObj.match", 5] } },
timezone: "Europe/Zurich"
}
}
}
},
{
$match: {
$expr: {
$gte: ["$DateObj", { $subtract: ["$$NOW", 200 * 60 * 60 * 24 * 1000] }]
}
}
},
{
"$group": {
_id: null,
"Volume": {
"$avg": "$Volume"
}
}
}
])
推荐阅读
- c# - 无法从 ADO.net 连接到 Firebird 服务器
- byte-buddy - 在 ElementMatchers.takesArguments() 中使用 TypeDefinition
- python - 如何在允许与 Python 不匹配的同时搜索子字符串并获取匹配索引?
- servicestack - TableAlias 不适用于多个连接
- c++ - 解释该代码中 std::max 的用法?
- linux - ldconfig 返回 255 退出代码
- c# - ASP.NET 我可以制作一个自定义属性来处理授权范围吗?
- swift - 字符串编码返回错误值。33.48 变为 33.47999999999999488
- wso2 - WSO2-IS 5.11.0 - 更新用户 - SCIM Rest Java 客户端应用程序
- haproxy - Haproxy URL 重定向