diff options
author | Eliot Horowitz <eliot@10gen.com> | 2009-08-20 16:50:58 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2009-08-20 16:50:58 -0400 |
commit | 792c9ea3f714c74b2fef567b0bc5a57579db0642 (patch) | |
tree | e9f1da946ac58cda7609e696362d71ffb4fb7eec | |
parent | afae0919bbf43392c00a06a6c7c03bee4e1b7813 (diff) | |
download | mongo-792c9ea3f714c74b2fef567b0bc5a57579db0642.tar.gz |
$mod operator
-rw-r--r-- | db/jsobj.cpp | 2 | ||||
-rw-r--r-- | db/jsobj.h | 1 | ||||
-rw-r--r-- | db/matcher.cpp | 14 | ||||
-rw-r--r-- | db/matcher.h | 13 | ||||
-rw-r--r-- | db/queryutil.cpp | 3 | ||||
-rw-r--r-- | jstests/mod1.js | 16 |
6 files changed, 47 insertions, 2 deletions
diff --git a/db/jsobj.cpp b/db/jsobj.cpp index bf44e9370cc..b872239310e 100644 --- a/db/jsobj.cpp +++ b/db/jsobj.cpp @@ -411,6 +411,8 @@ namespace mongo { if ( fn[1] == 'n' && fn[3] == 0 ) return BSONObj::NE; } + else if ( fn[1] == 'm' && fn[2] == 'o' && fn[3] == 'd' && fn[4] == 0 ) + return BSONObj::opMOD; else if ( fn[1] == 'i' && fn[2] == 'n' && fn[3] == 0 ) return BSONObj::opIN; else if ( fn[1] == 'n' && fn[2] == 'i' && fn[3] == 'n' && fn[4] == 0 ) diff --git a/db/jsobj.h b/db/jsobj.h index 9fd2a1b88ec..711c539a2a7 100644 --- a/db/jsobj.h +++ b/db/jsobj.h @@ -901,6 +901,7 @@ namespace mongo { opALL = 0x0B, NIN = 0x0C, opEXISTS = 0x0D, + opMOD = 0x0E }; }; ostream& operator<<( ostream &s, const BSONObj &o ); diff --git a/db/matcher.cpp b/db/matcher.cpp index bc6792c7e67..fac352a1d60 100644 --- a/db/matcher.cpp +++ b/db/matcher.cpp @@ -246,6 +246,11 @@ namespace mongo { basics.push_back( BasicMatcher( e , BSONObj::opIN , fe.embeddedObject() ) ); ok = true; } + else if ( fn[1] == 'm' && fn[2] == 'o' && fn[3] == 'd' && fn[4] == 0 && fe.type() == Array ) { + // $mod + basics.push_back( BasicMatcher( e , BSONObj::opMOD ) ); + ok = true; + } else if ( fn[1] == 'n' && fn[2] == 'i' && fn[3] == 'n' && fn[4] == 0 && fe.type() == Array ) { // $nin basics.push_back( BasicMatcher( e , BSONObj::NIN , fe.embeddedObject() ) ); @@ -315,7 +320,14 @@ namespace mongo { } return count == r.number(); } - + + if ( op == BSONObj::opMOD ){ + if ( ! l.isNumber() ) + return false; + + return l.numberLong() % bm.mod == bm.modm; + } + /* check LT, GTE, ... */ if ( !( l.isNumber() && r.isNumber() ) && ( l.type() != r.type() ) ) return false; diff --git a/db/matcher.h b/db/matcher.h index c814fe3c2cb..03b5b335845 100644 --- a/db/matcher.h +++ b/db/matcher.h @@ -57,9 +57,17 @@ namespace mongo { } BasicMatcher( BSONElement _e , int _op ) : toMatch( _e ) , compareOp( _op ){ + if ( _op == BSONObj::opMOD ){ + BSONObj o = _e.embeddedObject().firstElement().embeddedObject(); + mod = o["0"].numberInt(); + modm = o["1"].numberInt(); + + uassert( "mod can't be 0" , mod ); + uassert( "mod eq can't be 0" , modm ); + } } - + BasicMatcher( BSONElement _e , int _op , const BSONObj& array ) : toMatch( _e ) , compareOp( _op ){ myset.reset( new set<BSONElement,element_lt>() ); @@ -74,6 +82,9 @@ namespace mongo { BSONElement toMatch; int compareOp; shared_ptr< set<BSONElement,element_lt> > myset; + + int mod; + int modm; }; // SQL where clause equivalent diff --git a/db/queryutil.cpp b/db/queryutil.cpp index 2f7a2acf79a..a4d44f9e965 100644 --- a/db/queryutil.cpp +++ b/db/queryutil.cpp @@ -65,6 +65,9 @@ namespace mongo { } break; } + case BSONObj::opMOD: { + break; + } case BSONObj::opIN: { massert( "$in requires array", e.type() == Array ); BSONElement max = minKey.firstElement(); diff --git a/jstests/mod1.js b/jstests/mod1.js new file mode 100644 index 00000000000..c77b5091e89 --- /dev/null +++ b/jstests/mod1.js @@ -0,0 +1,16 @@ + +t = db.mod1; +t.drop(); + +t.save( { a : 1 } ); +t.save( { a : 2 } ); +t.save( { a : 11 } ); + +assert.eq( 2 , t.find( "this.a % 10 == 1" ).itcount() , "A" ); +assert.eq( 2 , t.find( { a : { $mod : [ 10 , 1 ] } } ).itcount() , "B" ); + +t.ensureIndex( { a : 1 } ); + +assert.eq( 2 , t.find( "this.a % 10 == 1" ).itcount() , "C" ); +assert.eq( 2 , t.find( { a : { $mod : [ 10 , 1 ] } } ).itcount() , "D" ); + |