Files
mongo/jstests/core/geo_mindistance.js
2016-05-28 17:55:12 -04:00

184 lines
6.0 KiB
JavaScript

/* Test $minDistance option for $near and $nearSphere queries, and geoNear
* command. SERVER-9395.
*/
var t = db.geo_mindistance;
t.drop();
//
// Useful constants and functions.
//
var km = 1000, earthRadiusMeters = 6378.1 * km;
function metersToRadians(m) {
return m / earthRadiusMeters;
}
/* Count documents within some radius of (0, 0), in kilometers.
* With this function we can use the existing $maxDistance option to test
* the newer $minDistance option's behavior.
*/
function n_docs_within(radius_km) {
// geoNear's distances are in meters for geoJSON points.
var cmdResult = db.runCommand({
geoNear: t.getName(),
near: {type: 'Point', coordinates: [0, 0]},
spherical: true,
maxDistance: radius_km * km,
num: 1000
});
return cmdResult.results.length;
}
//
// Setup.
//
/* Make 121 points from long, lat = (0, 0) (in Gulf of Guinea) to (10, 10)
* (inland Nigeria).
*/
for (var x = 0; x <= 10; x += 1) {
for (var y = 0; y <= 10; y += 1) {
t.insert({loc: [x, y]});
}
}
/* $minDistance is supported for 2dsphere index only, not 2d or geoHaystack. */
t.ensureIndex({loc: "2dsphere"});
var n_docs = t.count(), geoJSONPoint = {type: 'Point', coordinates: [0, 0]}, legacyPoint = [0, 0];
//
// Test $near with GeoJSON point (required for $near with 2dsphere index).
// min/maxDistance are in meters.
//
var n_min1400_count =
t.find({loc: {$near: {$geometry: geoJSONPoint, $minDistance: 1400 * km}}}).count();
assert.eq(n_docs - n_docs_within(1400),
n_min1400_count,
"Expected " + (n_docs - n_docs_within(1400)) +
" points $near (0, 0) with $minDistance 1400 km, got " + n_min1400_count);
var n_bw500_and_1000_count =
t.find({
loc: {$near: {$geometry: geoJSONPoint, $minDistance: 500 * km, $maxDistance: 1000 * km}}
}).count();
assert.eq(n_docs_within(1000) - n_docs_within(500),
n_bw500_and_1000_count,
"Expected " + (n_docs_within(1000) - n_docs_within(500)) +
" points $near (0, 0) with $minDistance 500 km and $maxDistance 1000 km, got " +
n_bw500_and_1000_count);
//
// $nearSphere with 2dsphere index can take a legacy or GeoJSON point.
// First test $nearSphere with legacy point.
// min/maxDistance are in radians.
//
n_min1400_count =
t.find({loc: {$nearSphere: legacyPoint, $minDistance: metersToRadians(1400 * km)}}).count();
assert.eq(n_docs - n_docs_within(1400),
n_min1400_count,
"Expected " + (n_docs - n_docs_within(1400)) +
" points $nearSphere (0, 0) with $minDistance 1400 km, got " + n_min1400_count);
n_bw500_and_1000_count = t.find({
loc: {
$nearSphere: legacyPoint,
$minDistance: metersToRadians(500 * km),
$maxDistance: metersToRadians(1000 * km)
}
}).count();
assert.eq(n_docs_within(1000) - n_docs_within(500),
n_bw500_and_1000_count,
"Expected " + (n_docs_within(1000) - n_docs_within(500)) +
" points $nearSphere (0, 0) with $minDistance 500 km and $maxDistance 1000 km, got " +
n_bw500_and_1000_count);
//
// Test $nearSphere with GeoJSON point.
// min/maxDistance are in meters.
//
n_min1400_count = t.find({loc: {$nearSphere: geoJSONPoint, $minDistance: 1400 * km}}).count();
assert.eq(n_docs - n_docs_within(1400),
n_min1400_count,
"Expected " + (n_docs - n_docs_within(1400)) +
" points $nearSphere (0, 0) with $minDistance 1400 km, got " + n_min1400_count);
n_bw500_and_1000_count =
t.find({
loc: {$nearSphere: geoJSONPoint, $minDistance: 500 * km, $maxDistance: 1000 * km}
}).count();
assert.eq(n_docs_within(1000) - n_docs_within(500),
n_bw500_and_1000_count,
"Expected " + (n_docs_within(1000) - n_docs_within(500)) +
" points $nearSphere (0, 0) with $minDistance 500 km and $maxDistance 1000 km, got " +
n_bw500_and_1000_count);
//
// Test geoNear command with GeoJSON point.
// Distances are in meters.
//
var cmdResult = db.runCommand({
geoNear: t.getName(),
near: {type: 'Point', coordinates: [0, 0]},
minDistance: 1400 * km,
spherical: true // spherical required for 2dsphere index
});
assert.eq(n_docs - n_docs_within(1400),
cmdResult.results.length,
"Expected " + (n_docs - n_docs_within(1400)) +
" points geoNear (0, 0) with $minDistance 1400 km, got " + cmdResult.results.length);
cmdResult = db.runCommand({
geoNear: t.getName(),
near: {type: 'Point', coordinates: [0, 0]},
minDistance: 500 * km,
maxDistance: 1000 * km,
spherical: true
});
assert.eq(n_docs_within(1000) - n_docs_within(500),
cmdResult.results.length,
"Expected " + (n_docs_within(1000) - n_docs_within(500)) +
" points geoNear (0, 0) with $minDistance 500 km and $maxDistance 1000 km, got " +
cmdResult.results.length);
//
// Test geoNear command with legacy point.
// Distances are in radians.
//
cmdResult = db.runCommand({
geoNear: t.getName(),
near: legacyPoint,
minDistance: metersToRadians(1400 * km),
spherical: true // spherical required for 2dsphere index
});
assert.eq(n_docs - n_docs_within(1400),
cmdResult.results.length,
"Expected " + (n_docs - n_docs_within(1400)) +
" points geoNear (0, 0) with $minDistance 1400 km, got " + cmdResult.results.length);
cmdResult = db.runCommand({
geoNear: t.getName(),
near: legacyPoint,
minDistance: metersToRadians(500 * km),
maxDistance: metersToRadians(1000 * km),
spherical: true
});
assert.eq(n_docs_within(1000) - n_docs_within(500),
cmdResult.results.length,
"Expected " + (n_docs_within(1000) - n_docs_within(500)) +
" points geoNear (0, 0) with $minDistance 500 km and $maxDistance 1000 km, got " +
cmdResult.results.length);