问题
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