Chidi Williams
Chidi Williams

Reputation: 399

MongoDB: Get all nearby with filter

In MongoDB, I have models of User, Token, and Boost.

A user can have one or more tokens and one or more boosts.

Token has a 2dsphere location field.

And Boost has startTime and stopTime Date fields.

A user is said to have an active boost if Date.now() is greater than boost.startTime() and less than boost.stopTime().

What Mongo aggregation can I write to fetch me all the tokens near a particular location that belong to users with at least one active boost?

Upvotes: 1

Views: 208

Answers (1)

Vish511
Vish511

Reputation: 96

Based on your question, I have created a mock data

token collection:
{
    "_id" : ObjectId("5b97541c6af22cc65216ffd8"),
    "userid" : "5b9753726af22cc65216ffd6",
    "location" : {
        "longitude" : 80.250875,
        "latitude" : 13.052519
    }
},
{
    "_id" : ObjectId("5b97543a6af22cc65216ffd9"),
    "userid" : "5b97537e6af22cc65216ffd7",
    "location" : {
        "longitude" : 80.249995,
        "latitude" : 13.051819
    }
}

boost collection :
{
        "_id" : ObjectId("5b9754796af22cc65216ffda"),
        "startTime" : ISODate("2018-09-11T05:36:57.149Z"),
        "stopTime" : ISODate("2018-09-11T05:36:57.149Z"),
        "userid" : "5b9753726af22cc65216ffd6"
    },
    {
        "_id" : ObjectId("5b9754b46af22cc65216ffdb"),
        "startTime" : ISODate("2018-10-08T18:30:00.000Z"),
        "stopTime" : ISODate("2018-10-08T18:30:00.000Z"),
        "userid" : "5b97537e6af22cc65216ffd7"
    }

Users collection :
{
            "_id" : ObjectId("5b9753726af22cc65216ffd6"),
            "userName" : "user111"
        },
        {
            "_id" : ObjectId("5b97537e6af22cc65216ffd7"),
            "userName" : "user222"
        }

The aggregate query to fetch all the tokens near a particular location that belong to users with at least one active boost is:

 db.token.aggregate([
{
     "$geoNear": {
        "near": { type: "Point", coordinates: [80.248797,13.050599] },
        "distanceField": "location",
        "maxDistance": 1000,
        "includeLocs": "location",
        "spherical": true
     }
   },
   {"$lookup" : {"from":"boost",
                 "localField" : "userid",
                "foreignField" : "userid",
                 "as" : "boostDocs"
      }},
   {"$unwind" : "$boostDocs"},
   {"$match" : {"$and":[{"boostDocs.startTime":{"$lte":new Date("11/09/2018")}},{"boostDocs.stopTime":{"$gte":new Date("10/09/2018")}}]}}
   ])

Notice that query to match the location is at the top of the query as $geoNear will only work if its the first stage of the aggregation pipeline. The Date that I've used for comparison is just to check if my query works. You can specify your date or Date.now() as per your requirement.

Upvotes: 1

Related Questions