Please let me know if there are better solutions. I am in need of a good solution, this is what I will use for the time being.
Your problem: Livequery documents within radius R of a lat-lng coordinate pair.
Meteor’s Problem: Live Geoqueries like $near
, $within
, etc. are not oplog-enabled and are not suitable for high traffic applications.
Simple Solution: If you want to find documents near a certain point, you don’t need to use geoqueries. One way around this is to store the lat-lng point in your document like this:
var yourDocument = {
name: "John Doe",
occupation: "Actor",
lat: 39.564,
lng: 134.342
};
Suppose we want to find a document near {lat: 38.456, lng: 133.332}
.
A simple way to do it:
var point = {lat: 38.456, lng: 133.332};
var dist = 5; //miles
var dLat = milesToLat(dist);
var dLng = milesToLng(dist);
//returns document above
People.findOne({
lat: {
$lte: point.lat + dLat,
$gte: point.lat - dLat
},
lng: {
$lte: point.lng + dLng,
$gte: point.lng - dLng
}
})
The above code will find documents within an approximately square region around the point, which may be good enough for many purposes. The main advantage is that Meteor can handle this query with the oplog (I think…). Another subtle advantage is in observer reuse:
var myLocation = {lat: 39.5561, lng: 145.6764}
var yourLocation = {lat: 39.5562, lng: 145.6766}
/*
Theory: Note how our locations are very close. Querying once
for each precise location will not allow us to take advantage of
observer reuse. If we approximate the locations as the same
location, then we can take advantage of Meteor's observer reuse.
Querying around a roundedLocation will likely show us the
same documents that would have been shown to us if we had
instead both queried around our exact Locations.
*/
var roundedLocation = {lat: 39.56, lng: 145.68};
Again, the disadvantage is losing accuracy in favor of performance.
Rounding a coordinate pair to four significant figures still gives us a delta of less than a mile for most locations.
For example, if I want to find nearby car repair shops, I don’t care if I accidentally get some results which are a half mile further than a more precise solution would have given me.
By combining a $lte, $gte
approach with value rounding, we can get pretty decent geoqueries!
Please let me know if there are better solutions. I am in need of a good solution, this is what I will use for the time being.