简体   繁体   中英

Find latest record based on Group Mongoose

I'm quite new to NoSQL and struggling to write this query I am using Mongoose on Node.js

What I want to achieve is to get ONE latest result based on Group of Device ID. I have no trouble writing this in SQL but having hard time doing it in NoSQL.

Here is the Model setup

_id     DeviceID     Coordinate:{lat, long}
1       2            lat: 1, long: 2
2       3            lat: 2, long: 3
3       1            lat: 3, long: 3
4       3            lat: 5, long: 4
5       2            lat: 7, long: 5
6       2            lat: 9, long: 6
7       3            lat: 111, long: 7
8       2            lat: 113, long: 8

The output that I want is:

_id     DeviceID     Coordinate:{lat, long}
3       1            lat: 3, long: 3
7       3            lat: 111, long: 7
8       2            lat: 113, long: 8

This is what I have tried but the result I've got is undefined

Note: beginDayID , endDayID are variables of mongoose ObjectId represents the _id of beginning and end of day.

mongoose.model('GPSData').aggregate([
  {$match: {_id:{$gte: beginDayID, $lt: endDayID}}},
  {$unwind: "$Coordinates"},
  {$project: {DeviceID: '$DeviceID' }},
  {$group: { DeviceID: '$DeviceID', $lat: '$Coordinates.lat', $long: '$Coordinates.long'}}

  ], (e, data) => {
     console.error(e)
     console.log(data)
     if (e) return callback(e, null);
     return callback(null, data);
   })

I assume you have documents somewhat similar to this

/* 1 */
{
    "_id" : 1,
    "DeviceID" : 1,
    "Coordinate" : {
        "lat" : 1,
        "long" : 2
    }
}

/* 2 */
{
    "_id" : 2,
    "DeviceID" : 2,
    "Coordinate" : {
        "lat" : 1,
        "long" : 6
    }
}
...

then an aggregation pipeline like this should work

mongoose.model('GPSData').aggregate([
  {
      $match: ... // your match filter criteria
  },
  {
      $sort: {
          _id: 1
      }
  },
  { 
      $group: { 
          _id: '$DeviceID',
          lastId: { $last: '$_id' },
          lat: { $last: '$Coordinate.lat' }, 
          long: { $last:'$Coordinate.long' }
      }
  },
  {
      $project: {
          _id: '$lastId',
          DeviceID: '$_id',
          lat: 1,
          long: 1
      }
  }
])

The output documents' shape look like this

/* 1 */
{
    "_id" : 1,
    "DeviceID" : 1,
    "Coordinate" : {
        "lat" : 1,
        "long" : 2
    }
}

/* 2 */
{
    "_id" : 2,
    "DeviceID" : 2,
    "Coordinate" : {
        "lat" : 1,
        "long" : 6
    }
}

Note the additional stage of $sort as you have to specify an order when talking about keeping the 'last values'. You may have to specify another sorting if you have other requirements

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