Adds progressive search functionality for $geoNear operations, allowing better integration with other cursors.
168 lines
6.4 KiB
JavaScript
168 lines
6.4 KiB
JavaScript
t = db.borders
|
|
t.drop()
|
|
|
|
epsilon = 0.0001;
|
|
|
|
// For these tests, *required* that step ends exactly on max
|
|
min = -1
|
|
max = 1
|
|
step = 1
|
|
numItems = 0;
|
|
|
|
for ( var x = min; x <= max; x += step ) {
|
|
for ( var y = min; y <= max; y += step ) {
|
|
t.insert( { loc : { x : x, y : y } } )
|
|
numItems++;
|
|
}
|
|
}
|
|
|
|
overallMin = -1
|
|
overallMax = 1
|
|
|
|
// Create a point index slightly smaller than the points we have
|
|
var res = t.ensureIndex({ loc: "2d" },
|
|
{ max: overallMax - epsilon / 2,
|
|
min: overallMin + epsilon / 2 });
|
|
assert.commandFailed(res);
|
|
|
|
// Create a point index only slightly bigger than the points we have
|
|
res = t.ensureIndex( { loc : "2d" }, { max : overallMax + epsilon, min : overallMin - epsilon } );
|
|
assert.commandWorked(res);
|
|
|
|
// ************
|
|
// Box Tests
|
|
// ************
|
|
|
|
// If the bounds are bigger than the box itself, just clip at the borders
|
|
assert.eq( numItems, t.find(
|
|
{ loc : { $within : { $box : [
|
|
[ overallMin - 2 * epsilon, overallMin - 2 * epsilon ],
|
|
[ overallMax + 2 * epsilon, overallMax + 2 * epsilon ] ] } } } ).count() );
|
|
|
|
// Check this works also for bounds where only a single dimension is off-bounds
|
|
assert.eq( numItems - 5, t.find(
|
|
{ loc : { $within : { $box : [
|
|
[ overallMin - 2 * epsilon, overallMin - 0.5 * epsilon ],
|
|
[ overallMax - epsilon, overallMax - epsilon ] ] } } } ).count() );
|
|
|
|
// Make sure we can get at least close to the bounds of the index
|
|
assert.eq( numItems, t.find(
|
|
{ loc : { $within : { $box : [
|
|
[ overallMin - epsilon / 2, overallMin - epsilon / 2 ],
|
|
[ overallMax + epsilon / 2, overallMax + epsilon / 2 ] ] } } } ).count() );
|
|
|
|
// Make sure we can get at least close to the bounds of the index
|
|
assert.eq( numItems, t.find(
|
|
{ loc : { $within : { $box : [
|
|
[ overallMax + epsilon / 2, overallMax + epsilon / 2 ],
|
|
[ overallMin - epsilon / 2, overallMin - epsilon / 2 ] ] } } } ).count() );
|
|
|
|
// Check that swapping min/max has good behavior
|
|
assert.eq( numItems, t.find(
|
|
{ loc : { $within : { $box : [
|
|
[ overallMax + epsilon / 2, overallMax + epsilon / 2 ],
|
|
[ overallMin - epsilon / 2, overallMin - epsilon / 2 ] ] } } } ).count() );
|
|
|
|
assert.eq( numItems, t.find(
|
|
{ loc : { $within : { $box : [
|
|
[ overallMax + epsilon / 2, overallMin - epsilon / 2 ],
|
|
[ overallMin - epsilon / 2, overallMax + epsilon / 2 ] ] } } } ).count() );
|
|
|
|
// **************
|
|
// Circle tests
|
|
// **************
|
|
|
|
center = ( overallMax + overallMin ) / 2
|
|
center = [ center, center ]
|
|
radius = overallMax
|
|
|
|
offCenter = [ center[0] + radius, center[1] + radius ]
|
|
onBounds = [ offCenter[0] + epsilon, offCenter[1] + epsilon ]
|
|
offBounds = [ onBounds[0] + epsilon, onBounds[1] + epsilon ]
|
|
onBoundsNeg = [ -onBounds[0], -onBounds[1] ]
|
|
|
|
// Make sure we can get all points when radius is exactly at full bounds
|
|
assert.lt( 0, t.find( { loc : { $within : { $center : [ center, radius + epsilon ] } } } ).count() );
|
|
|
|
// Make sure we can get points when radius is over full bounds
|
|
assert.lt( 0, t.find( { loc : { $within : { $center : [ center, radius + 2 * epsilon ] } } } ).count() );
|
|
|
|
// Make sure we can get points when radius is over full bounds, off-centered
|
|
assert.lt( 0, t.find( { loc : { $within : { $center : [ offCenter, radius + 2 * epsilon ] } } } ).count() );
|
|
|
|
// Make sure we get correct corner point when center is in bounds
|
|
// (x bounds wrap, so could get other corner)
|
|
cornerPt = t.findOne( { loc : { $within : { $center : [ offCenter, step / 2 ] } } } );
|
|
assert.eq( cornerPt.loc.y, overallMax )
|
|
|
|
// Make sure we get correct corner point when center is on bounds
|
|
// NOTE: Only valid points on MIN bounds
|
|
cornerPt = t
|
|
.findOne( { loc : { $within : { $center : [ onBoundsNeg, Math.sqrt( 2 * epsilon * epsilon ) + ( step / 2 ) ] } } } );
|
|
assert.eq( cornerPt.loc.y, overallMin )
|
|
|
|
// Make sure we can't get corner point when center is over bounds
|
|
// TODO: SERVER-5800 clean up wrapping rules for different CRS queries - not sure this is an error
|
|
/*
|
|
assert.throws(function(){
|
|
t.findOne( { loc : { $within : { $center : [ offBounds, Math.sqrt( 8 * epsilon * epsilon ) + ( step / 2 ) ] } } } );
|
|
});
|
|
*/
|
|
|
|
|
|
// Make sure we can't get corner point when center is on max bounds
|
|
// Broken - see SERVER-13581
|
|
//assert.throws(function(){
|
|
// t.findOne( { loc : { $within : { $center : [ onBounds, Math.sqrt( 8 * epsilon * epsilon ) + ( step / 2 ) ] } } } );
|
|
//});
|
|
|
|
// ***********
|
|
// Near tests
|
|
// ***********
|
|
|
|
// Make sure we can get all nearby points to point in range
|
|
assert.eq( overallMax, t.find( { loc : { $near : offCenter } } ).next().loc.y );
|
|
|
|
// Make sure we can get all nearby points to point on boundary
|
|
assert.eq( overallMin, t.find( { loc : { $near : onBoundsNeg } } ).next().loc.y );
|
|
|
|
// Make sure we can't get all nearby points to point over boundary
|
|
// TODO: SERVER-9986 clean up wrapping rules for different CRS queries - not sure this is an error
|
|
/*
|
|
assert.throws(function(){
|
|
t.findOne( { loc : { $near : offBounds } } );
|
|
});
|
|
*/
|
|
|
|
// Make sure we can't get all nearby points to point on max boundary
|
|
//Broken - see SERVER-13581
|
|
//assert.throws(function(){
|
|
// t.findOne( { loc : { $near : onBoundsNeg } } );
|
|
//});
|
|
|
|
// Make sure we can get all nearby points within one step (4 points in top
|
|
// corner)
|
|
assert.eq( 4, t.find( { loc : { $near : offCenter, $maxDistance : step * 1.9 } } ).count() );
|
|
|
|
// **************
|
|
// Command Tests
|
|
// **************
|
|
// Make sure we can get all nearby points to point in range
|
|
assert.eq( overallMax, db.runCommand( { geoNear : "borders", near : offCenter } ).results[0].obj.loc.y );
|
|
|
|
// Make sure we can get all nearby points to point on boundary
|
|
assert.eq( overallMin, db.runCommand( { geoNear : "borders", near : onBoundsNeg } ).results[0].obj.loc.y );
|
|
|
|
// Make sure we can't get all nearby points to point over boundary
|
|
//TODO: SERVER-9986 clean up wrapping rules for different CRS queries - not sure this is an error
|
|
/*
|
|
assert.commandFailed( db.runCommand( { geoNear : "borders", near : offBounds } ));
|
|
*/
|
|
|
|
// Make sure we can't get all nearby points to point on max boundary
|
|
assert.commandWorked( db.runCommand( { geoNear : "borders", near : onBounds } ));
|
|
|
|
// Make sure we can get all nearby points within one step (4 points in top
|
|
// corner)
|
|
assert.eq( 4, db.runCommand( { geoNear : "borders", near : offCenter, maxDistance : step * 1.5 } ).results.length );
|