summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2010-04-01 15:32:52 -0400
committerEliot Horowitz <eliot@10gen.com>2010-04-01 15:33:50 -0400
commitfc7f36ad702fc1b45b17b0e1d08586c8faf77a72 (patch)
treec0305105b4c4e706fe5e073382094992f9125c21
parenta57baf1d0505012b045619e8a6ee0733c9f27fea (diff)
downloadmongo-fc7f36ad702fc1b45b17b0e1d08586c8faf77a72.tar.gz
first cut at radius limiting $near SERVER-813
-rw-r--r--db/index_geo2d.cpp22
-rw-r--r--jstests/geo2.js5
2 files changed, 21 insertions, 6 deletions
diff --git a/db/index_geo2d.cpp b/db/index_geo2d.cpp
index 4730c29cbfd..a5e15c20125 100644
--- a/db/index_geo2d.cpp
+++ b/db/index_geo2d.cpp
@@ -893,14 +893,14 @@ namespace mongo {
public:
typedef multiset<GeoPoint> Holder;
- GeoHopper( const Geo2dType * g , unsigned max , const GeoHash& n , const BSONObj& filter = BSONObj() )
- : GeoAccumulator( g , filter ) , _max( max ) , _near( n ) {
+ GeoHopper( const Geo2dType * g , unsigned max , const GeoHash& n , const BSONObj& filter = BSONObj() , double maxDistance = numeric_limits<double>::max() )
+ : GeoAccumulator( g , filter ) , _max( max ) , _near( n ), _maxDistance( maxDistance ) {
}
virtual bool checkDistance( const GeoHash& h , double& d ){
d = _g->distance( _near , h );
- bool good = _points.size() < _max || d < farthest();
+ bool good = d < _maxDistance && ( _points.size() < _max || d < farthest() );
GEODEBUG( "\t\t\t\t\t\t\t checkDistance " << _near << "\t" << h << "\t" << d
<< " ok: " << good << " farthest: " << farthest() );
return good;
@@ -926,6 +926,7 @@ namespace mongo {
unsigned _max;
GeoHash _near;
Holder _points;
+ double _maxDistance;
};
@@ -999,10 +1000,10 @@ namespace mongo {
class GeoSearch {
public:
- GeoSearch( const Geo2dType * g , const GeoHash& n , int numWanted=100 , BSONObj filter=BSONObj() )
+ GeoSearch( const Geo2dType * g , const GeoHash& n , int numWanted=100 , BSONObj filter=BSONObj() , double maxDistance = numeric_limits<double>::max() )
: _spec( g ) , _n( n ) , _start( n ) ,
_numWanted( numWanted ) , _filter( filter ) ,
- _hopper( new GeoHopper( g , numWanted , n , filter ) )
+ _hopper( new GeoHopper( g , numWanted , n , filter , maxDistance ) )
{
assert( g->getDetails() );
_nscanned = 0;
@@ -1478,7 +1479,16 @@ namespace mongo {
switch ( e.embeddedObject().firstElement().getGtLtOp() ){
case BSONObj::opNEAR: {
e = e.embeddedObject().firstElement();
- shared_ptr<GeoSearch> s( new GeoSearch( this , _tohash(e) , numWanted , query ) );
+ double maxDistance = numeric_limits<double>::max();
+ if ( e.isABSONObj() && e.embeddedObject().nFields() > 2 ){
+ BSONObjIterator i(e.embeddedObject());
+ i.next();
+ i.next();
+ BSONElement e = i.next();
+ if ( e.isNumber() )
+ maxDistance = e.numberDouble();
+ }
+ shared_ptr<GeoSearch> s( new GeoSearch( this , _tohash(e) , numWanted , query , maxDistance ) );
s->exec();
auto_ptr<Cursor> c;
c.reset( new GeoSearchCursor( s ) );
diff --git a/jstests/geo2.js b/jstests/geo2.js
index b9452c890e4..6b1a1a2e72e 100644
--- a/jstests/geo2.js
+++ b/jstests/geo2.js
@@ -41,3 +41,8 @@ assert.close( fast.stats.avgDistance , a( t.find( { loc : { $near : [ 50 , 50 ]
printjson( t.find( { loc : { $near : [ 50 , 50 ] } } ).explain() )
+assert.lt( 3 , a( t.find( { loc : { $near : [ 50 , 50 ] } } ).limit(50) ) , "C1" )
+assert.gt( 3 , a( t.find( { loc : { $near : [ 50 , 50 , 3 ] } } ).limit(50) ) , "C2" )
+
+
+