0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

checkpoint on $near op

This commit is contained in:
Eliot Horowitz 2010-02-25 16:24:34 -05:00
parent 3d2b4f8ad4
commit f08ba724c3
10 changed files with 78 additions and 7 deletions

View File

@ -46,6 +46,8 @@ namespace mongo {
const IndexPlugin * getPlugin() const { return _plugin; }
virtual auto_ptr<Cursor> newCursor( const BSONObj& query , const BSONObj& order ) const = 0;
virtual BSONObj fixKey( const BSONObj& in ) { return in; }
protected:

View File

@ -327,6 +327,12 @@ namespace mongo {
return _spec->getDetails();
}
virtual auto_ptr<Cursor> newCursor( const BSONObj& query , const BSONObj& order ) const {
auto_ptr<Cursor> c;
assert(0);
return c;
}
const IndexSpec* _spec;
string _geo;
vector<string> _other;

View File

@ -436,8 +436,12 @@ namespace mongo {
else if ( fn[3] == 'e' && fn[4] == 0 ) return BSONObj::LTE;
}
}
else if ( fn[1] == 'n' && fn[2] == 'e' && fn[3] == 0)
return BSONObj::NE;
else if ( fn[1] == 'n' && fn[2] == 'e' ){
if ( fn[3] == 0 )
return BSONObj::NE;
if ( fn[3] == 'a' && fn[4] == 'r' && fn[5] == 0 )
return BSONObj::opNEAR;
}
else if ( fn[1] == 'm' && fn[2] == 'o' && fn[3] == 'd' && fn[4] == 0 )
return BSONObj::opMOD;
else if ( fn[1] == 't' && fn[2] == 'y' && fn[3] == 'p' && fn[4] == 'e' && fn[5] == 0 )

View File

@ -993,7 +993,8 @@ namespace mongo {
opTYPE = 0x0F,
opREGEX = 0x10,
opOPTIONS = 0x11,
opELEM_MATCH = 0x12
opELEM_MATCH = 0x12,
opNEAR = 0x13
};
};
ostream& operator<<( ostream &s, const BSONObj &o );

View File

@ -248,6 +248,8 @@ namespace mongo {
flags = fe.valuestrsafe();
break;
}
case BSONObj::opNEAR:
break;
default:
uassert( 10069 , (string)"BUG - can't operator for: " + fn , 0 );
}

View File

@ -63,7 +63,7 @@ namespace mongo {
QueryPlan::QueryPlan(
NamespaceDetails *_d, int _idxNo,
const FieldRangeSet &fbs, const BSONObj &order, const BSONObj &startKey, const BSONObj &endKey ) :
const FieldRangeSet &fbs, const BSONObj &order, const BSONObj &startKey, const BSONObj &endKey , string special ) :
d(_d), idxNo(_idxNo),
fbs_( fbs ),
order_( order ),
@ -73,7 +73,8 @@ namespace mongo {
exactKeyMatch_( false ),
direction_( 0 ),
endKeyInclusive_( endKey.isEmpty() ),
unhelpful_( false ) {
unhelpful_( false ),
_special( special ){
if ( !fbs_.matchPossible() ) {
unhelpful_ = true;
@ -90,6 +91,12 @@ namespace mongo {
return;
}
if ( _special.size() ){
optimal_ = true;
scanAndOrderRequired_ = false; // TODO: maybe part of key spec?
return;
}
BSONObj idxKey = index_->keyPattern();
BSONObjIterator o( order );
BSONObjIterator k( idxKey );
@ -179,6 +186,13 @@ namespace mongo {
}
auto_ptr< Cursor > QueryPlan::newCursor( const DiskLoc &startLoc ) const {
if ( _special.size() ){
IndexType * type = index_->getSpec().getType();
massert( 13040 , (string)"no type for special: " + _special , type );
return type->newCursor( fbs_.query() , order_ );
}
if ( !fbs_.matchPossible() ){
if ( fbs_.nNontrivialRanges() )
checkTableScanAllowed( fbs_.ns() );
@ -322,6 +336,23 @@ namespace mongo {
}
}
if ( fbs_.getSpecial().size() ){
string special = fbs_.getSpecial();
NamespaceDetails::IndexIterator i = d->ii();
while( i.more() ) {
int j = i.pos();
IndexDetails& ii = i.next();
if ( ii.getSpec().getTypeName() == special ){
usingPrerecordedPlan_ = true;
mayRecordPlan_ = true;
plans_.push_back( PlanPtr( new QueryPlan( d , j , fbs_ , order_ ,
BSONObj() , BSONObj() , special ) ) );
return;
}
}
uassert( 13038 , (string)"can't find special index: " + special , 0 );
}
if ( honorRecordedPlan_ ) {
boostlock lk(NamespaceDetailsTransient::_qcMutex);
NamespaceDetailsTransient& nsd = NamespaceDetailsTransient::get_inlock( ns );

View File

@ -32,7 +32,8 @@ namespace mongo {
const FieldRangeSet &fbs,
const BSONObj &order,
const BSONObj &startKey = BSONObj(),
const BSONObj &endKey = BSONObj() );
const BSONObj &endKey = BSONObj() ,
string special="" );
/* If true, no other index can do better. */
bool optimal() const { return optimal_; }
@ -70,6 +71,7 @@ namespace mongo {
BoundList indexBounds_;
bool endKeyInclusive_;
bool unhelpful_;
string _special;
};
// Inherit from this interface to implement a new query operation.

View File

@ -253,6 +253,9 @@ namespace mongo {
log() << "warning: shouldn't get here?" << endl;
break;
}
case BSONObj::opNEAR:
_special = "2d";
break;
default:
break;
}
@ -312,6 +315,8 @@ namespace mongo {
intervals_ = newIntervals;
for( vector< BSONObj >::const_iterator i = other.objData_.begin(); i != other.objData_.end(); ++i )
objData_.push_back( *i );
if ( _special.size() == 0 && other._special.size() )
_special = other._special;
return *this;
}
@ -325,6 +330,17 @@ namespace mongo {
return o;
}
string FieldRangeSet::getSpecial() const {
string s = "";
for ( map<string,FieldRange>::iterator i=ranges_.begin(); i!=ranges_.end(); i++ ){
if ( i->second.getSpecial().size() == 0 )
continue;
uassert( 13033 , "can't have 2 special fields" , s.size() == 0 );
s = i->second.getSpecial();
}
return s;
}
void FieldRangeSet::processOpElement( const char *fieldName, const BSONElement &f, bool isNot, bool optimize ) {
int op2 = f.getGtLtOp();
if ( op2 == BSONObj::opELEM_MATCH ) {
@ -389,7 +405,7 @@ namespace mongo {
processOpElement( e.fieldName(), f, true, optimize );
break;
default:
uassert( 13033, "invalid use of $not", false );
uassert( 13041, "invalid use of $not", false );
}
} else {
processOpElement( e.fieldName(), f, false, optimize );

View File

@ -69,11 +69,14 @@ namespace mongo {
}
bool empty() const { return intervals_.empty(); }
const vector< FieldInterval > &intervals() const { return intervals_; }
string getSpecial() const { return _special; }
private:
BSONObj addObj( const BSONObj &o );
string simpleRegexEnd( string regex );
vector< FieldInterval > intervals_;
vector< BSONObj > objData_;
string _special;
};
// implements query pattern matching, used to determine if a query is
@ -171,6 +174,7 @@ namespace mongo {
}
QueryPattern pattern( const BSONObj &sort = BSONObj() ) const;
BoundList indexBounds( const BSONObj &keyPattern, int direction ) const;
string getSpecial() const;
private:
void processOpElement( const char *fieldName, const BSONElement &f, bool isNot, bool optimize );
static FieldRange *trivialRange_;

View File

@ -34,3 +34,6 @@ printjson( slow.stats )
slow.results.forEach( p )
*/
//t.find( { loc : { $near : [ 50 , 50 ] } } ).itcount();