简体   繁体   中英

How to subtract two dates in mongoDb aggregate inside $group?

I am trying to calculate login time of user based on data in mongoDB whenever user login. I have login startDateTime , endDateTime and duration fields but if duration is 0 then it should take the difference of current date time and startDateTime .

The problem I got here is result is wrong because I have checked by subtracting the same dates in browser console using new Date() .

Here is the aggregate query I am trying

    let queryFilter = {
    createdAt: {
      "$gte": filter.from ? new Date(filter.from) : new Date(new Date().toDateString()),
      "$lte": filter.to ? new Date(filter.to) : new Date(new Date().toDateString())
    }
  }


AgentJournal.aggregate([
    {
      $match: queryFilter
    },
    {
      $group: {
        _id: { agent: "$agent", queue: "$queue", channel: "$channel" },
        loginTime: { "$sum": { "$cond": [{ "$eq": ["$event", "LOGIN"] }, { "$cond": [{ "$eq": ["$duration", 0] }, { $subtract: [new Date(), new Date("$startDateTime")] }, "$duration"] }, 0] } },
      }
    }
  ])

This is a sample document stored in my database:

{
    "_id" : ObjectId("608a6ee3e781511b7283c393"),
    "duration" : 0,
    "agent" : "SIP/intellicon",
    "queue" : "sales",
    "event" : "LOGIN",
    "startDateTime" : "2021-04-29 13:27:21",  //String Type
    "endDateTime" : "0000-00-00 00:00:00",    //String Type
    "channel" : "fb_pages",
    "__v" : 0,
    "createdAt" : ISODate("2021-04-29T08:31:31.995Z"),
    "updatedAt" : ISODate("2021-04-29T08:31:31.995Z")
}

Note: I have checked by subtracting integers it works accurate so I think my query is OK

Try $toDate operator to convert your string date to date type,

{
  $subtract: [
    new Date(),
    { $toDate: "$startDateTime" }
  ]
}

Playground

i have resolved it by using the $toDate told by @turivishal as well as convert the new Date to my local standard time first (ie new Date().toLocaleString() ) and then pass it to $toDate (ie {$toDate:new Date().toLocaleString} )

now the query to calculate login time is

loginTime: { "$sum": { "$cond": [{ "$eq": ["$event", "LOGIN"] }, { "$cond": [{ "$eq": ["$duration", 0] }, { $subtract: [{ $toDate: new Date().toLocaleString() }, { $toDate: "$startDateTime" }] }, "$duration"] }, 0] } },

Thanks Again @turivishal

https://docs.mongodb.com/manual/reference/operator/aggregation/dateDiff/

{
   $dateDiff: {
      startDate: <Expression>,
      endDate: <Expression>,
      unit: <Expression>,
      timezone: <tzExpression>,
      startOfWeek: <String>
   }
}

subtract value return in milliseconds

  const avgTime = await Activity.aggregate<{
    count?: string;
    avg_time: string;
  }>([
    {
      $match: {
        finishedAt: {
          $exists: true,
        },
      },
    },
    {
      $unwind: '$tags',
    },
    {
      $match: {
        $or: t,
      },
    },
    {
      $group: {
        _id: null,
        count: {
          $sum: 1,
        },
        avg_time: {
          $avg: {
            // $subtract: [
            //   {
            //     $ifNull: ['$finishedAt', 0],
            //   },
            //   {
            //     $ifNull: ['$createdAt', 0],
            //   },
            // ],
            $subtract: ['$finishedAt', '$createdAt'],
            //$subtract: [{ $toDate: '$finishedAt' }, { $toDate: '$createdAt' }],
          },
        },
      },
    },
  ]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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