mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
159 lines
4.0 KiB
JavaScript
159 lines
4.0 KiB
JavaScript
//
|
|
// Tests the error handling of spherical queries
|
|
// along with multi-location documents.
|
|
// This is necessary since the error handling must manage
|
|
// multiple documents, and so requires simultaneous testing.
|
|
//
|
|
|
|
var numTests = 30
|
|
|
|
for ( var test = 0; test < numTests; test++ ) {
|
|
|
|
//var fixedTest = 6017
|
|
//if( fixedTest ) test = fixedTest
|
|
|
|
Random.srand( 1337 + test );
|
|
|
|
var radius = 5000 * Random.rand() // km
|
|
radius = radius / 6371 // radians
|
|
var numDocs = Math.floor( 400 * Random.rand() )
|
|
// TODO: Wrapping uses the error value to figure out what would overlap...
|
|
var bits = Math.floor( 5 + Random.rand() * 28 )
|
|
var maxPointsPerDoc = 50
|
|
|
|
t = db.sphere
|
|
|
|
var randomPoint = function() {
|
|
return [ Random.rand() * 360 - 180, Random.rand() * 180 - 90 ];
|
|
}
|
|
|
|
// Get a start point that doesn't require wrapping
|
|
// TODO: Are we a bit too aggressive with wrapping issues?
|
|
var startPoint
|
|
var ex = null
|
|
do {
|
|
|
|
t.drop()
|
|
startPoint = randomPoint()
|
|
t.ensureIndex( { loc : "2d" }, { bits : bits } )
|
|
|
|
try {
|
|
// Check for wrapping issues
|
|
t.find( { loc : { $within : { $centerSphere : [ startPoint, radius ] } } } ).toArray()
|
|
ex = null
|
|
} catch (e) {
|
|
ex = e
|
|
}
|
|
} while (ex)
|
|
|
|
var pointsIn = 0
|
|
var pointsOut = 0
|
|
var docsIn = 0
|
|
var docsOut = 0
|
|
var totalPoints = 0
|
|
|
|
//var point = randomPoint()
|
|
|
|
for ( var i = 0; i < numDocs; i++ ) {
|
|
|
|
var numPoints = Math.floor( Random.rand() * maxPointsPerDoc + 1 )
|
|
var docIn = false
|
|
var multiPoint = []
|
|
|
|
totalPoints += numPoints
|
|
|
|
for ( var p = 0; p < numPoints; p++ ) {
|
|
var point = randomPoint()
|
|
multiPoint.push( point )
|
|
|
|
if ( Geo.sphereDistance( startPoint, point ) <= radius ) {
|
|
pointsIn++
|
|
docIn = true
|
|
} else {
|
|
pointsOut++
|
|
}
|
|
}
|
|
|
|
t.insert( { loc : multiPoint } )
|
|
|
|
if ( docIn )
|
|
docsIn++
|
|
else
|
|
docsOut++
|
|
|
|
}
|
|
|
|
printjson( { test: test,
|
|
radius : radius, bits : bits, numDocs : numDocs, pointsIn : pointsIn, docsIn : docsIn, pointsOut : pointsOut,
|
|
docsOut : docsOut } )
|
|
|
|
assert.isnull( db.getLastError() )
|
|
assert.eq( docsIn + docsOut, numDocs )
|
|
assert.eq( pointsIn + pointsOut, totalPoints )
|
|
|
|
// $centerSphere
|
|
assert.eq( docsIn, t.find( { loc : { $within : { $centerSphere : [ startPoint, radius ] } } } ).count() )
|
|
|
|
// $nearSphere
|
|
var results = t.find( { loc : { $nearSphere : startPoint, $maxDistance : radius } } ).limit( 2 * pointsIn )
|
|
.toArray()
|
|
|
|
assert.eq( pointsIn, results.length )
|
|
|
|
var distance = 0;
|
|
for ( var i = 0; i < results.length; i++ ) {
|
|
|
|
var minNewDistance = radius + 1
|
|
for( var j = 0; j < results[i].loc.length; j++ ){
|
|
var newDistance = Geo.sphereDistance( startPoint, results[i].loc[j] )
|
|
if( newDistance < minNewDistance && newDistance >= distance ) minNewDistance = newDistance
|
|
}
|
|
|
|
//print( "Dist from : " + results[i].loc[j] + " to " + startPoint + " is "
|
|
// + minNewDistance + " vs " + radius )
|
|
|
|
assert.lte( minNewDistance, radius )
|
|
assert.gte( minNewDistance, distance )
|
|
distance = minNewDistance
|
|
|
|
}
|
|
|
|
// geoNear
|
|
var results = db.runCommand( {
|
|
geoNear : "sphere", near : startPoint, maxDistance : radius, num : 2 * pointsIn, spherical : true } ).results
|
|
|
|
/*
|
|
printjson( results );
|
|
|
|
for ( var j = 0; j < results[0].obj.loc.length; j++ ) {
|
|
var newDistance = Geo.sphereDistance( startPoint, results[0].obj.loc[j] )
|
|
if( newDistance <= radius ) print( results[0].obj.loc[j] + " : " + newDistance )
|
|
}
|
|
*/
|
|
|
|
assert.eq( pointsIn, results.length )
|
|
|
|
var distance = 0;
|
|
for ( var i = 0; i < results.length; i++ ) {
|
|
var retDistance = results[i].dis
|
|
|
|
// print( "Dist from : " + results[i].loc + " to " + startPoint + " is "
|
|
// + retDistance + " vs " + radius )
|
|
|
|
var distInObj = false
|
|
for ( var j = 0; j < results[i].obj.loc.length && distInObj == false; j++ ) {
|
|
var newDistance = Geo.sphereDistance( startPoint, results[i].obj.loc[j] )
|
|
distInObj = ( newDistance >= retDistance - 0.0001 && newDistance <= retDistance + 0.0001 )
|
|
}
|
|
|
|
assert( distInObj )
|
|
assert.lte( retDistance, radius )
|
|
assert.gte( retDistance, distance )
|
|
distance = retDistance
|
|
}
|
|
|
|
//break;
|
|
}
|
|
|
|
|