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

Add medianKey command

This commit is contained in:
Aaron 2009-03-27 11:53:47 -04:00
parent 5ad67c509f
commit 790b17c6a6
4 changed files with 88 additions and 2 deletions

View File

@ -263,11 +263,15 @@ namespace mongo {
return s;
}
BSONObj prettyKey( const BSONObj &key ) const {
return key.replaceFieldNames( indexDetails.keyPattern() ).clientReadable();
}
virtual BSONObj prettyStartKey() const {
return startKey.replaceFieldNames( indexDetails.keyPattern() ).clientReadable();
return prettyKey( startKey );
}
virtual BSONObj prettyEndKey() const {
return endKey.replaceFieldNames( indexDetails.keyPattern() ).clientReadable();
return prettyKey( endKey );
}
private:

View File

@ -798,6 +798,53 @@ namespace mongo {
}
} cmdFileMD5;
class CmdMedianKey : public Command {
public:
CmdMedianKey() : Command( "medianKey" ) {}
virtual bool slaveOk() { return true; }
virtual void help( stringstream &help ) const {
help << " example: { medianKey:\"blog.posts\", keyPattern:{x:1} min:{x:10}, max:{x:55} }";
}
bool run(const char *dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ){
const char *ns = jsobj.getStringField( "medianKey" );
BSONObj keyPattern = jsobj.getObjectField( "keyPattern" );
BSONObj min = jsobj.getObjectField( "min" ).extractFieldsUnDotted( keyPattern );
BSONObj max = jsobj.getObjectField( "max" ).extractFieldsUnDotted( keyPattern );
if ( ns[ 0 ] == '\0' || keyPattern.isEmpty() || min.isEmpty() || max.isEmpty() ) {
errmsg = "invalid command syntax";
return false;
}
setClient( ns );
const IndexDetails *id = 0;
NamespaceDetails *d = nsdetails( ns );
for (int i = 0; i < d->nIndexes; i++ ) {
IndexDetails& ii = d->indexes[i];
if( ii.keyPattern().woCompare(keyPattern) == 0 ) {
id = &ii;
break;
}
}
if ( !id ) {
errmsg = "no index found for specified keyPattern";
return false;
}
Timer t;
int num = 0;
for( BtreeCursor c( *id, min, max, 1 ); c.ok(); c.advance(), ++num );
num /= 2;
BtreeCursor c( *id, min, max, 1 );
for( ; num; c.advance(), --num );
int ms = t.millis();
if ( ms > 100 ) {
out() << "Finding median for index: " << keyPattern << " between " << min << " and " << max << " took " << ms << "ms." << endl;
}
result.append( "median", c.prettyKey( c.currKey() ) );
return true;
}
} cmdMedianKey;
extern map<string,Command*> *commands;
/* TODO make these all command objects -- legacy stuff here

33
jstests/median.js Normal file
View File

@ -0,0 +1,33 @@
f = db.jstests_median;
f.drop();
f.ensureIndex( {i:1} );
for( i = 0; i < 1000; ++i ) {
f.save( {i:i} );
}
assert.eq( 500, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1}, min:{i:0}, max:{i:999} } ).median.i );
assert.eq( 0, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1}, min:{i:0}, max:{i:0} } ).median.i );
assert.eq( 500, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1}, min:{i:500}, max:{i:500} } ).median.i );
assert.eq( 1, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1}, min:{i:0}, max:{i:1} } ).median.i );
assert.eq( 1, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1}, min:{i:0}, max:{i:2} } ).median.i );
f.drop();
f.ensureIndex( {i:1,j:-1} );
for( i = 0; i < 100; ++i ) {
for( j = 0; j < 100; ++j ) {
f.save( {i:i,j:j} );
}
}
assert.eq( 50, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:0,j:0}, max:{i:99,j:0} } ).median.i );
assert.eq( 0, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:0,j:0}, max:{i:0,j:0} } ).median.i );
assert.eq( 50, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:50,j:0}, max:{i:50,j:0} } ).median.i );
assert.eq( 1, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:0,j:0}, max:{i:1,j:0} } ).median.i );
assert.eq( 1, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:0,j:0}, max:{i:2,j:0} } ).median.i );
assert.eq( 49, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:0,j:99}, max:{i:0,j:0} } ).median.j );
assert.eq( 44, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:0,j:49}, max:{i:0,j:40} } ).median.j );
assert.eq( 10, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:10,j:50}, max:{i:11,j:75} } ).median.i );
assert.eq( 12, db.runCommand( {medianKey:"test.jstests_median", keyPattern:{i:1,j:-1}, min:{i:10,j:50}, max:{i:11,j:75} } ).median.j );

View File

@ -246,6 +246,7 @@
93D9469F0F7ABB0600C3C768 /* repl6.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = repl6.js; sourceTree = "<group>"; };
93D948200F7BF4FA00C3C768 /* remove5.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = remove5.js; sourceTree = "<group>"; };
93D948210F7BF4FA00C3C768 /* shellfork.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = shellfork.js; sourceTree = "<group>"; };
93D949B40F7D2A7700C3C768 /* median.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = median.js; sourceTree = "<group>"; };
93E3C5310F704C9D0029011E /* repl4.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = repl4.js; sourceTree = "<group>"; };
93E3C5960F7149F40029011E /* repl5.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = repl5.js; sourceTree = "<group>"; };
93E727090F4B5B5B004F9B5D /* shardkey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shardkey.cpp; sourceTree = "<group>"; };
@ -530,6 +531,7 @@
93A8D1D10F37544800C92B85 /* jstests */ = {
isa = PBXGroup;
children = (
93D949B40F7D2A7700C3C768 /* median.js */,
93D948200F7BF4FA00C3C768 /* remove5.js */,
93D948210F7BF4FA00C3C768 /* shellfork.js */,
93D19B300F5EF09C0084C329 /* clone */,