Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
   })
like image 650
XPLOT1ON Avatar asked Aug 03 '16 17:08

XPLOT1ON


People also ask

How do I get the latest record in MongoDB?

MongoDB find() method is used to select documents from a specified collection. It also set the cursor position to the selected document. The default find() method gets the documents from the start of the collection.

What is $first in MongoDB?

$first selects the first document from each output group: The _id: null group is included. When the accumulator field, $quantity in this example, is missing, $first returns null .

What is $$ root?

$$ROOT. The $$ROOT variable contains the source documents for the group. If you'd like to just pass them through unmodified, you can do this by $pushing $$ROOT into the output from the group.

What is $last in MongoDB?

This means $last returns the last order type for the documents between the current document and the end of the partition.


1 Answers

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

like image 162
DAXaholic Avatar answered Sep 24 '22 06:09

DAXaholic