Locations specified as sub-doc or array • Ordering in points must be consistent ... and be careful of your hashes • Spherical queries have additional caveats ... we'll get there
}) Queries ordered by distance: position : [ $near, $nearSphere ] Queries within bounds, no ordering: position : { $within : [ $center, $box, $polygon, $centerSphere ] } Whenever possible, go for unordered queries.
care • Longitude and latitude are angles • Distances in spherical queries are entered and returned in radians • No wrapping at the poles and date line - detected and error thrown
approximate paths depending on segment length. • Multi-location docs with many locations will perform better with $within queries, as do single-location queries
people living within (roughly)100 miles > // of the Empire State Building. > // Second argument to $center is the radius. > var q = {'$within': {'$center': [[-73.985656, 40.748433], 100 / (3963 * (Math.PI / 180))]}}> var sum = 0 > var cur = db.zips.find({'loc': q}) > for( var i = 0; i < cur.length(); i++ ){ ... sum += cur[i].pop;... } 23266107
• Calculate accurate spherical distances • $nearSphere or $centerSphere ◦ $boxSphere doesn't really make sense :-) • For geoNear add 'spherical: true' option • There are some caveats...
• Must be specified in longitude / latitude order • All distances returned in radians ◦ Multiply by Earth's radius to get distance in useful units ▪ e.g. ~6371 km or ~3963 miles ◦ Divide by Earth's radius for maxDistance • Doesn't handle wrapping at poles or the transition from -180° to +180° longitude
miles of the> // Empire State Building (again). > var sum = 0 > var maxdist = 100 / 3963 > // limit(100) is default if not specified...> var cur = db.zips.find({'loc': {'$nearSphere': [-73.985656, 40.748433], $maxDistance: maxdist}}).limit(60000)> for(var i = 0; i < cur.length(); i++){ ... sum += cur[i]. pop;... }26452212 > // Was 23266107 in our previous non-spherical attempt.