Optimizing for distance

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.

  • Clear DB
  • Create user 1 in Santiago
  • Create user 4 in Valparaiso
  • Check whether there is a match
  • Create user 2 in Santiago
  • Check whether there was a match between 1 and 2
  • Create user 3 in Vancouver
  • Check whether 3 has a match
  • Create user 5 in Valparaiso
  • Check whether there is a match between 4 & 5

(Source:git checkout 52e8f80b7fe3b9482ff27ea1bcc410270752a796)

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.202.209