I have a situation where I need to calculate the distance between users. In this particular scenario I have:
Employer geolocation - One user one location. Candidate geolocation - One location for each user but when the employer generates the list of candidates there are multiple candidates.
I'm currently successfully pushing geolocations down the wire and running a rudimentary distance formula on the client side to figure out the distance between the employer and each candidate on the fly and then showing/hiding the candidates, as per the request.
I've been told that I should be running the calculation on the server side and just pushing down a single number, ie. 10 representing 10km, for each candidate. Then running a filter on that number.
So far, I have only pushed collections and fields down the wire. Is it possible to run the formula below on the server side and just pass down one number and 'attach' it to a user?
The second question is, what would be best practice for Meteor?
I'm still learning to code, so apologies if this is a really obvious question.
Client Side
Path: List.js
specialisations = specialisations.filter(function(element){
let distance = Template.instance().distanceFromEmployerFilter.get();
let user = Meteor.users.findOne({_id: element.candidateUserId});
let candidateLat = user && user.profile && user.profile.address && user.profile.address.latitude;
let candidateLong = user && user.profile && user.profile.address && user.profile.address.longitude;
let company = CompanyDetails.findOne({employerUserId: Meteor.userId()});
let companyLat = company && company.latitude;
let companyLong = company && company.longitude;
var R = 6371; // Radius of the earth in km
var dLat = (companyLat-candidateLat) * (Math.PI/180);
var dLon = (companyLong-candidateLong) * (Math.PI/180);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos((candidateLat) * (Math.PI/180)) * Math.cos((companyLat) * (Math.PI/180)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var distanceInKM = R * c; // Distance in km
if (distanceInKM <= distance) {
return true;
} else {
return false;
}
});
I'd do the filtering on the fetching of the candidates to display. Either as you publish/subscribe on your template or as you fetch in your helper:
Meteor.users.find({
"profile.address" : {
$near: {
$geometry: {
type: "Point" ,
coordinates: [ <Employerlongitude> , <Employerlatitude> ]
},
$maxDistance: <distance in meters>,
$minDistance: <distance in meters>
}}}).fetch();
If address is a 2d index. Specify coordinates in this order: “longitude, latitude.”
from Mongodb docs :
$near Specifies a point for which a geospatial query returns the documents from nearest to farthest. The $near operator can specify either a GeoJSON point or legacy coordinate point.
$minDistance & $maxDistance are optional