MongoDB : near + lookup in aggregation query

二次信任 提交于 2020-01-03 01:55:12

问题


I would like to know if this is even possible.

Actually my query is : a near query on Users table + a forEach loop of find queries on UserSports table where user._id = userId of UserSports (it's like a join done in a foreach) :

    //geonear query
    db.users.find({
        geopoint_mongo:
           {$near:
                  {$geometry: {type: "Point", coordinates: [userGeopoint.lng, userGeopoint.lat]},
                        $maxDistance: maxDistance * 1000
                  }
           }
    },
    {_id: 1, geopoint: 1, url_avatar: 1, bool_coach: 1, bool_ambassador: 1, gender: 1, bool_handicap: 1}
    ).toArray(function (err, usersFound) {
        if (usersFound && usersFound.length > 0) {
            var count = 0;
            var total = usersFound.length;
            var users = [];
            // start the loop
            usersFound.forEach(function (user) {
                // find with condition query
                db.userSports.find({
                    userId: user._id,
                    sportId: {$in: sportIds}
                },
                {_id: 1, user_level: 1, sportId: 1}
                ).toArray(function (err, userSports) {
                    count++;
                    if (userSports && userSports.length > 0) {
                        user.userSports = userSports;
                        users.push(user);
                    }
                    if (count === total) {
                        console.log('Done');
                    }
                });
            });
        }
    });

I heard you can use $lookup and aggregate to do the join, because actually my queries take too much time - but I wasn't able to find any example of this. At least, is there a solution to run this code faster?


回答1:


You can use below aggregation query with $lookup stage in 3.4 version.

db.users.aggregate([
  {"$match":{ // Match to find users in location
    "geopoint_mongo":{
      "$near":{
        "$geometry":{"type":"Point","coordinates":[userGeopoint.lng, userGeopoint.lat]},
        "$maxDistance":maxDistance*1000
      }
    }
  }},
  {"$project":{ // Keep fields from users collection
    "geopoint":1,"url_avatar":1,"bool_coach":1,"bool_ambassador":1,"gender":1,"bool_handicap":1
  }},
  {"$lookup":{ // Join user with user sports collection
    "from":"userSports",
    "localField":"_id",
    "foreignField":"userId",
    "as":"sports"
  }},
  {"$unwind":"$sports"}, // $unwind + $match to get matching sports
  {"$match":{"sports.sportId":{"$in":sportIds}}},
  {"$addFields":{"sports._id":1,"sports.user_level":1,"sports.sportId":1}}, // Keep fields from user sports collection
  {"$group":{
    "_id":"$_id",
    "geopoint":{"$first":"$geopoint"},// Keep fields from users collection
    "bool_coach":{"$first":"$bool_coach"},
    "bool_ambassador":{"$first":"$bool_ambassador"},
    "gender":{"$first":"$gender"},
    "bool_handicap":{"$first":"$bool_handicap"},
    "sports":{"$push":"$sports"} // Collect matching sports
  }}
])



回答2:


In such a aggregation query we have to consider The aggregation pipeline. Bellow code will help you to identify syntax for this query

db.driversLocation.aggregate([

    {
        $geoNear: {
            near: {type: "Point", coordinates:[parseFloat(req.query.latitude), parseFloat(req.query.longitude )]},
            distanceField: "dist.calculated",
            maxDistance:10000,
            spherical: true
        }

    },

    {

    $lookup:
    {
        from: "drivers",
        localField: "driverId",
        foreignField: "oid",
        as: "mas"
    },

    },{
        $match:{
            "mas.vehicle.bodyType": "lorry"
        }
    },

]


来源:https://stackoverflow.com/questions/40340147/mongodb-near-lookup-in-aggregation-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!