Let's use a down-to-earth geolocation approach (ah! I'm so funny) to the match. We have to be realistic. Our service was born in Smallville but it's going global and we can't match people who are too far apart.
Because our meetings are arranged free of racing conditions on the Meeting
collection and we would like to keep it that way, let's adapt our existing pair
method to incorporate the user's location. We can assume that at registration, they will supply their location (or we could also easily update the meeting document once they provide the location). In our existing strategy, we have one user who creates a meeting document; in this case, let's also set their location, so the next user looking for a match will have to be in a similar location as an additional constraint, as shown in the following code:
'''javascript Meeting.ensureIndex({location1: "2dsphere"}); //.. methods.pair = function(user,done) { methods.userMatchHistory(user, function(err, emailList) { if(err) return done(err); Meeting.findAndModify({ new: true, query: { user2: {$exists: false}, 'user1.email': {$nin: emailList}, 'location1': {$nearSphere:{ $geometry : { type : 'Point', coordinates : user.location } , $maxDistance : 7*1000 }} }, update: { $set: { user2: user, at: arrangeTime() } } }, function(err, newPair) { if (err) { return done(err); } if (newPair){ return done(null, newPair); } Meeting.insert({ user1: user, location1: user.location }, function(err,meeting) { done(); }) return; }); }); } '''
Our Meeting
collection now has location1
indexed as 2dsphere
. The geoquery for this field can easily be integrated with our previous query, using the operator $nearSphere
to match geo positions in a sphere object. $maxDistance
is the maximum radius for the match. It's expressed in meters and in this case, we intersect the coordinates with Point
, which is a previously registered user. 7km
was chosen arbitrarily because it seems like a reasonable enough radius to meet someone.
If we changed $maxDistance
to something considerably smaller, some of our tests would fail because matches wouldn't happen; see test/meeting_near.js
.
(Source:git checkout 52e8f80b7fe3b9482ff27ea1bcc410270752a796)