Following are the fields with some sample data of my collection for geolocation of all the users on every 30 seconds.
Data Collection Documents
[{
"_id": id1,
"purpose": "tracking",
"user": User1,
"geoLocation": {
"type": "Point",
"coordinates": [73.11892896428128, 22.31833064059432]
},
"createdAt": ISODate("2023-05-08T10:08:15.049Z"),
"updatedAt": ISODate("2023-05-08T10:08:15.049Z")
},
{
"_id": id2,
"purpose": "tracking",
"user": User1,
"geoLocation": {
"type": "Point",
"coordinates": [73.09304942391326, 22.321831847174654]
},
"createdAt": ISODate("2023-05-08T10:09:43.828Z"),
"updatedAt": ISODate("2023-05-08T10:09:43.828Z")
},
{
"_id": id3,
"purpose": "tracking",
"user": User2,
"geoLocation": {
"type": "Point",
"coordinates": [73.14348330367717, 22.280082608116277]
},
"createdAt": ISODate("2023-05-08T10:12:30.670Z"),
"updatedAt": ISODate("2023-05-08T10:12:30.670Z")
},
{
"_id": id4,
"purpose": "tracking",
"user": User2,
"geoLocation": {
"type": "Point",
"coordinates": [73.1542041657593, 22.27487612032671]
},
"createdAt": ISODate("2023-05-08T10:13:10.224Z"),
"updatedAt": ISODate("2023-05-08T10:13:10.224Z")
}
]
As per the above data there are 2 users with 2 locations with different timinigs(Old, New)
Now, I am trying to fetch the records which are near to specific point with users latest locations(New) and ignore the old or previous records of the same users. Here is the query which I am using.
Please Check Data Query Section
Now it is returning the following 2 objects. Please check the Current Result Section
But the result should be like following. Please check the Expected Result Section
Now following is the distance of each location from the DB Origin Coordinates Distance Data
id1 - 3123
id2 - 5864
id3 - 3528
id4 - 2267
But as per the current result, Query is fetching the result of id1 for the User1 because it matches the maxDistance option of geoNear but the result should be fetched of id2 as it is the latest result. It is showing fine for User2 because both the location satisfies the maxDistance and latest result is being retrieved.
I have already checked the related questions for this almost similar issue but the issue was not checked with the same query. I am attaching related question as well.
MongoDB geoNear with Distinct and Sorted values
Can anyone guide me what should be the solution in this case? I hope my question is quite clear for this issue.
Thanks in advance and Any help is really appreciated.
Data Query
DBModel.aggregate([
{
$geoNear: {
near: { type: "Point", coordinates: [73.1528821581882, 22.29557552397352] },
key: "geoLocation",
distanceField: "distanceCalculated",
minDistance: 0,
maxDistance: 3000,
query: { purpose: "tracking" },
spherical: true,
},
},
{
$sort: {
user: 1,
createdAt: -1,
},
},
{
$group: {
_id: "$user",
geoLocation: {
$first: "$geoLocation",
},
createdAt: {
$first: "$createdAt",
},
},
},
])
(Current Result)
[{
"_id": id1,
"purpose": "tracking",
"user": User1,
"geoLocation": {
"type": "Point",
"coordinates": [73.11892896428128, 22.31833064059432]
},
"createdAt": ISODate("2023-05-08T10:08:15.049Z"),
"updatedAt": ISODate("2023-05-08T10:08:15.049Z"),
"distanceCalculated": 3123
},
{
"_id": id4,
"purpose": "tracking",
"user": User2,
"geoLocation": {
"type": "Point",
"coordinates": [73.1542041657593, 22.27487612032671]
},
"createdAt": ISODate("2023-05-08T10:13:10.224Z"),
"updatedAt": ISODate("2023-05-08T10:13:10.224Z"),
"distanceCalculated": 2267
}
]
Expected Result
[
{
"_id": id4,
"purpose": "tracking",
"user": User2,
"geoLocation": {
"type": "Point",
"coordinates": [73.1542041657593, 22.27487612032671]
},
"createdAt": ISODate("2023-05-08T10:13:10.224Z"),
"updatedAt": ISODate("2023-05-08T10:13:10.224Z"),
"distanceCalculated": 2267
}
]
If you want to get only the users that their latest location is in a specific range from a point, you have several ways of doing it, which you can choose from according to your data. Ideally, you would group by user and keep only the latest and then run
$geonearfor this users, but this can't be done, as$geonearcan only be the first step of the aggregation. Two other options are:$geonearwithout themaxDistancelimit, but keep the distance on the document, then group and keep only users where their last location document is according to the limit. This will work on a small data set, or if most of your documents are in range anyway, but for a large data set, where only a small portion of the documents are in range you can do:$geonearwith themaxDistancelimit, so you'll keep only a small portion of your documents. Then group by user and keep only the latest (from the documents in range). Next use$lookupwith pipeline to find for each user in range if they have another, more updated, document that should filter them out.In both cases you should probably use the
querypart of$geonearto filter only documents with relevantupdatedAt, for example, last 24 hours...The second option will look like: