【问题标题】:MongoDB Aggregation by Name and Different Time IntervalMongoDB 按名称和不同时间间隔聚合
【发布时间】:2018-01-04 22:21:08
【问题描述】:

我已经找了几天的解决方案,但我无法得到结果。请帮帮我!

我在 MongoDB 中有一个数据:

{ name: 'apple', date: 2018-01-04T10:00:00.000Z, price: 100 }
{ name: 'apple', date: 2018-01-04T10:01:00.000Z, price: 101 }
{ name: 'apple', date: 2018-01-04T10:02:00.000Z, price: 102 }
{ name: 'apple', date: 2018-01-04T10:03:00.000Z, price: 103 }
{ name: 'apple', date: 2018-01-04T10:04:00.000Z, price: 102 }
{ name: 'apple', date: 2018-01-04T10:05:00.000Z, price: 104 }

{ name: 'cherry', date: 2018-01-04T10:00:00.000Z, price: 53 }
{ name: 'cherry', date: 2018-01-04T10:01:00.000Z, price: 55 }
{ name: 'cherry', date: 2018-01-04T10:02:00.000Z, price: 51 }
{ name: 'cherry', date: 2018-01-04T10:03:00.000Z, price: 51 }
{ name: 'cherry', date: 2018-01-04T10:04:00.000Z, price: 50 }
{ name: 'cherry', date: 2018-01-04T10:05:00.000Z, price: 52 }

{ name: 'melon', date: 2018-01-04T10:00:00.000Z, price: 133 }
{ name: 'melon', date: 2018-01-04T10:01:00.000Z, price: 132 }
{ name: 'melon', date: 2018-01-04T10:02:00.000Z, price: 136 }
{ name: 'melon', date: 2018-01-04T10:03:00.000Z, price: 137 }
{ name: 'melon', date: 2018-01-04T10:04:00.000Z, price: 138 }
{ name: 'melon', date: 2018-01-04T10:05:00.000Z, price: 140 }

我想通过一个查询得到这个结果。

{name: 'apple', price_last: 104, price_1m_ago: 102, price_5m_ago: 100}
{name: 'cherry', price_last: 52, price_1m_ago: 50, price_5m_ago: 53}
{name: 'melon', price_last: 140, price_1m_ago: 138, price_5m_ago: 133}

我尝试使用聚合,但无法以任何方式构建有效查询。

food.aggregate([
    {
        $group: {
            _id: "$name",
            price_last: {$last:"$price"},
        }
    }
]}

【问题讨论】:

    标签: mongodb mongoose aggregation-framework


    【解决方案1】:

    如果您的数据保证每分钟包含一个元素,并且中间没有丢失数据,则可以很容易地实现,如下所示:

    food.aggregate([{
        $sort: {
            date: 1 // make sure the data is sorted by date
        }
    }, {
        $group: {
            _id: "$name",
            prices: { $push: "$price" }, // create an array per "name" with all prices in it
        }
    }, {
        $project: {
            name: "$_id",
            price_last: { $arrayElemAt: [ "$prices", -1 ] }, // select the first from the end of the array
            price_1m_ago:  { $arrayElemAt: [ "$prices", -2 ] }, // select the second from the end
            price_5m_ago:  { $arrayElemAt: [ "$prices", -6 ] } // select the 6th from the end
        }
    }])
    

    【讨论】:

    • 感谢您的回答!不幸的是,时间间隔是随机的。有时 1 秒内有 2-3 个价格,有时 1 分钟内只有一个。当 3d 方服务器上的价格发生变化时,价格会写入 DB。
    • 那么1m_ago5m_ago是什么意思呢?上一次可用价格更新前 1/5 分钟还是当前日期前 1 分钟?
    • 当前日期前 1m_ago。
    【解决方案2】:

    我得到了这个结果,@Avij 第一个查询。这里有一些重复。如果我用 new Date() 替换 $minute:'$lastdate',查询将不起作用。

    { _id: 'melon',
        lastPrice: 1575,
        five_min_price: 1573 },
      { _id: 'cherry',
        lastPrice: 60165,
        five_min_price: 59098 },
      { _id: 'apple',
        lastPrice: 0153,
        five_min_price: 0155 },
      { _id: 'apple',
        lastPrice: 0153,
        five_min_price: 0154 },
      { _id: 'apple',
        lastPrice: 0153,
        five_min_price: 0155 },
      { _id: 'apricot',
        lastPrice: 6897,
        five_min_price: 6235 },
      { _id: 'apricot',
        lastPrice: 6897,
        five_min_price: 6235 },
      { _id: 'apricot',
        lastPrice: 6897,
        five_min_price: 6822 },
      { _id: 'apricot',
        lastPrice: 6897,
        five_min_price: 683 },
      { _id: 'cucumber',
        lastPrice: 3461,
        five_min_price: 3533 },
      { _id: 'cucumber',
        lastPrice: 3461,
        five_min_price: 3496 },
      { _id: 'orange',
        lastPrice: 5366,
        five_min_price: 5367 }
    

    也许可以用 $match 来剪切查询,然后在这个结果中排在最后。如果数据库中的日期以 Unix 格式存储。这适用于一个结果,但我如何获得 10s/30s/1m/5m/10m/30m/1h 会导致一个查询。

    var now = new Date();
    var shift_5_min = shift_5_min = new Date( now.valueOf() - ( 5*60*1000 );
    
    "$match": {
        "date": { "$lte": shift_5_min" }
    }
    $group: {
         id: "$name",
         price: {$last: "$price"}
    }
    

    【讨论】:

    • 你的时间里也有“秒”吗?因为这里的样本数据中的每一个地方的秒数都是0,请检查实际数据中是否也有秒数?
    • 你想只跟踪一些时间间隔还是每隔一个时间间隔?..也请你的 Mongodb 版本
    • 秒数也不同。 DB中存储的完整日期为:ISODate(2018-01-04T14:14:47.290Z),s和ms不同。我想每 1 秒跟踪一次价格。数据以不同的时间段保存到数据库,每个产品从 1 到 5 秒。我想使用 socket.io 跟踪网站上的实时价格,并按时间间隔比较结果。假设苹果的价格比过去 10 分钟变化了 5%,比前一小时变化了 7%。 @Avij
    • 我的 MongoDB 版本是 v3.6.0 @Avij
    • 有什么想法吗? @Avij
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 1970-01-01
    相关资源
    最近更新 更多