iT邦幫忙

1

mongodb query 某月每一天特定時間區間

我想依照台電電費計價方法,實現時間計價
例如:
每日7.30~22.30為4元
其餘時間為3元

第一步要先query時間區間,再計算錢
用過regex但好像無法在timestamp做處理,想請問神人有什麼方法能達到該功能???

也好奇台電公司是如何實現得

//stage 1
{
$match: {"Timestamp":{$gte:new ISODate("2019-02-01T00:00:00Z"),$lt:new ISODate("2019-03-01T00:00:00Z")}}
},//找到當月
//stage 2
{
$match: {"Timestamp":{$gte:{$regex:/T07:30:/},$lte:{$regex:/T22:30:/}}}
}//找到該區間

1 個回答

1
dragonH
iT邦研究生 4 級 ‧ 2019-05-21 14:15:33
最佳解答

testDB的資料

/* 1 */
{
    "_id" : ObjectId("5ce373448bcb5b44bb2680da"),
    "value" : 300.0,
    "time" : Timestamp(1550206800, 1),
    "timeFormat" : "2019-02-15 13:00"
}

/* 2 */
{
    "_id" : ObjectId("5ce373a98bcb5b44bb2680db"),
    "value" : 500.0,
    "time" : Timestamp(1550347200, 1),
    "timeFormat" : "2019-02-17 04:00"
}

/* 3 */
{
    "_id" : ObjectId("5ce374398bcb5b44bb2680dc"),
    "value" : 99.0,
    "time" : Timestamp(1550538000, 1),
    "timeFormat" : "2019-02-19 09:00"
}

/* 4 */
{
    "_id" : ObjectId("5ce374448bcb5b44bb2680dd"),
    "value" : 25.0,
    "time" : Timestamp(1551034800, 1),
    "timeFormat" : "2019-02-25 03:00"
}

/* 5 */
{
    "_id" : ObjectId("5ce377ac11202e254546d235"),
    "value" : 66,
    "time" : Timestamp(1552244400, 1),
    "timeFormat" : "2019-03-11 03:00"
}

/* 6 */
{
    "_id" : ObjectId("5ce377e211202e254546d284"),
    "value" : 23,
    "time" : Timestamp(1553281200, 1),
    "timeFormat" : "2019-03-23 03:00"
}

/* 7 */
{
    "_id" : ObjectId("5ce389f88bcb5b44bb2680df"),
    "value" : 152.0,
    "time" : Timestamp(1558415864, 1)
}

/* 8 */
{
    "_id" : ObjectId("5ce38fe111202e254546e5bd"),
    "value" : 60,
    "time" : Timestamp(1551196200, 1),
    "timeFormat" : "2019-02-26 23:50"
}

/* 9 */
{
    "_id" : ObjectId("5ce3906911202e254546e62a"),
    "value" : 354,
    "time" : Timestamp(1551141900, 1),
    "timeFormat" : "2019-02-26 08:45"
}

1 .
找出 2019-02-01 00:00:00 到 2019-03-01 00:00:00(不含)間
符合 4元 計算的資料 (07:30 ~ 22:30)

db.getCollection('testDB').aggregate([
  {
    $project: {
      value:1,
      time: 1,
      timeFormat:1,
      passTime: {
        $add: [
          {
            $multiply: [
              {
                $hour: {
                  date: '$time',
                  timezone: '+08:00',
                },
              }, 60,
            ],
          },
          {
            $minute: '$time',
          },
        ],
      },
    },
  },
  {
    $match: {
      time: {
        $gte: Timestamp(1548950400, 1),
        $lt: Timestamp(1551369600, 1),
      },
      passTime: {
        $gte: 450,
        $lte: 1350,
      },
    },
  },
]);

result

/* 1 */
{
    "_id" : ObjectId("5ce373448bcb5b44bb2680da"),
    "value" : 300.0,
    "time" : Timestamp(1550206800, 1),
    "timeFormat" : "2019-02-15 13:00",
    "passTime" : 780.0
}

/* 2 */
{
    "_id" : ObjectId("5ce374398bcb5b44bb2680dc"),
    "value" : 99.0,
    "time" : Timestamp(1550538000, 1),
    "timeFormat" : "2019-02-19 09:00",
    "passTime" : 540.0
}

/* 3 */
{
    "_id" : ObjectId("5ce3906911202e254546e62a"),
    "value" : 354,
    "time" : Timestamp(1551141900, 1),
    "timeFormat" : "2019-02-26 08:45",
    "passTime" : 525.0
}

2 .
找出 2019-02-01 00:00:00 到 2019-03-01 00:00:00(不含)間
符合 3元 計算的資料 (00:00 ~ 07:30 或 22:30 ~ 23:59)

db.getCollection('testDB').aggregate([
  {
    $project: {
      value:1,
      time: 1,
      timeFormat:1,
      passTime: {
        $add: [
          {
            $multiply: [
              {
                $hour: {
                  date: '$time',
                  timezone: '+08:00',
                },
              }, 60,
            ],
          },
          {
            $minute: '$time',
          },
        ],
      },
    }
  },
  {
    $match: {
      time: {
        $gte: Timestamp(1548950400, 1),
        $lt: Timestamp(1551369600, 1),
      },
      $or: [
        {
          passTime: {
            $lt: 450,
          }
        },
        {
          passTime: {
            $gt: 1350,
          }
        }
      ],
    }
  }
]);

result

/* 1 */
{
    "_id" : ObjectId("5ce373a98bcb5b44bb2680db"),
    "value" : 500.0,
    "time" : Timestamp(1550347200, 1),
    "timeFormat" : "2019-02-17 04:00",
    "passTime" : 240.0
}

/* 2 */
{
    "_id" : ObjectId("5ce374448bcb5b44bb2680dd"),
    "value" : 25.0,
    "time" : Timestamp(1551034800, 1),
    "timeFormat" : "2019-02-25 03:00",
    "passTime" : 180.0
}

/* 3 */
{
    "_id" : ObjectId("5ce38fe111202e254546e5bd"),
    "value" : 60,
    "time" : Timestamp(1551196200, 1),
    "timeFormat" : "2019-02-26 23:50",
    "passTime" : 1430.0
}

結論:

不要搞自己 

乖乖撈完當月資料後

再來用後端慢慢算

真要這樣做的話

存資料時

多存 hours 跟 minutes

這兩個欄位應該會比較好

以上拙見
kay_wu iT邦新手 5 級 ‧ 2019-05-22 14:24:12 檢舉

挖屋~ 感謝大大救出深陷泥沼的我
完全沒想到過多存欄位/images/emoticon/emoticon07.gif

我要發表回答

立即登入回答