diff options
author | Eliot Horowitz <eliot@10gen.com> | 2010-04-01 15:32:52 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2010-04-01 15:33:50 -0400 |
commit | fc7f36ad702fc1b45b17b0e1d08586c8faf77a72 (patch) | |
tree | c0305105b4c4e706fe5e073382094992f9125c21 | |
parent | a57baf1d0505012b045619e8a6ee0733c9f27fea (diff) | |
download | mongo-fc7f36ad702fc1b45b17b0e1d08586c8faf77a72.tar.gz |
first cut at radius limiting $near SERVER-813
-rw-r--r-- | db/index_geo2d.cpp | 22 | ||||
-rw-r--r-- | jstests/geo2.js | 5 |
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" ) + + + |