简体   繁体   English

在 MongoDB 聚合和 NodeJS 中计算过去 200 天的平均值

[英]Calculating the average for last 200 days in MongoDB aggregation and NodeJS

I have a script which is calculating the average Volume data for every collection in my MongoDB.我有一个脚本,用于计算 MongoDB 中每个集合的平均Volume数据。 But since I have more that a 1000 days in record I wish to calculate the Average Volume only for last 200 days.但由于我有超过 1000 天的记录,我希望仅计算过去 200 天的Average Volume

Currently my script taking the whole data which is in collection (1000days+).目前我的脚本正在收集正在收集的全部数据(1000 天+)。

Goal: How I can setup a range of last 200 days to calculate the average Volume for them.目标:我如何设置过去 200 天的范围来计算他们的平均Volume Also pretty important thing that every next day I still want to use only last 200 days.还有一件很重要的事,就是隔天我还想只用最后 200 天。

Average aggregation Framework平均聚合框架

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 After editing the code like this >> 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();

I receive this error > MongoError: A pipeline stage specification object must contain exactly one field.我收到此错误 > MongoError: A pipeline stage specification object must contain exactly one field.

EDIT2 Code After having code like below I receive this error - MongoError: unknown top level operator: $gte 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"
                    }
                }
            }
        ])

Here is how document looks like in MongoDB.这是 MongoDB 中文档的样子。

在此处输入图像描述

EDIT3 Here is how my code looks like regarding the last improvement. EDIT3这是我的代码关于最后一次改进的样子。 Code is working the only problem It didn't return me average.代码是唯一的问题它没有返回我的平均水平。 In my terminal I receive an empty array [] but I don't receive any error.在我的终端中,我收到一个空数组[]但我没有收到任何错误。 I'm thinking that the problem is here - "$dateTime" I think the query for it is wrong.我认为问题就在这里 - "$dateTime"我认为查询它是错误的。 Cause I'm also trying to make it in MongoDB Compass.因为我也试图在 MongoDB Compass 中实现它。 Doesn't work as well.也不行。

Code Here代码在这里

  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();

EDIT4编辑4

The only problem now that I receive an empty array > [] I receive an empty array cause the Date is saving as string to MongoDB but to make aggregation framework work I need to store it as object .现在唯一的问题是我收到一个空数组 > []我收到一个空数组,因为Date保存为string到 MongoDB 但要使聚合框架工作,我需要将它存储为object

In code below there is my way of creating Date function it saves it in MongoDB as string how I can change it to save it as object在下面的代码中,有我创建日期 function 的方法,它将它作为string保存在 MongoDB 我如何更改它以将其保存为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)
    }
};

Document from MongoDB as text:来自 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
}

You have to filter documents before you group them.您必须在对文档进行分组之前对其进行过滤。 Should be like this:应该是这样的:

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"
         }
      }
   }
])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM