在MongoDB聚合和NodeJS中计算最近200天的平均值

时间:2020-07-17 12:18:23

标签: javascript node.js mongodb

我有一个脚本,用于计算MongoDB中每个集合的平均Volume数据。但是由于记录的时间已经超过1000天,所以我只想计算最近200天的Average Volume

目前,我的脚本正在收集收集中的所有数据(超过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中文档的外观。

enter image description here

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

EDIT4

现在唯一的问题是我收到一个空数组> []我收到一个空数组,原因是Date被另存为string到MongoDB,但是要使聚合框架正常工作,我需要将其存储为object

在下面的代码中,我有一种创建Date函数的方法,它将它以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)
    }
};

来自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
}

1 个答案:

答案 0 :(得分:1)

在对文档进行分组之前,必须先对其进行过滤。应该是这样的:

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