summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2009-08-20 16:50:58 -0400
committerEliot Horowitz <eliot@10gen.com>2009-08-20 16:50:58 -0400
commit792c9ea3f714c74b2fef567b0bc5a57579db0642 (patch)
treee9f1da946ac58cda7609e696362d71ffb4fb7eec
parentafae0919bbf43392c00a06a6c7c03bee4e1b7813 (diff)
downloadmongo-792c9ea3f714c74b2fef567b0bc5a57579db0642.tar.gz
$mod operator
-rw-r--r--db/jsobj.cpp2
-rw-r--r--db/jsobj.h1
-rw-r--r--db/matcher.cpp14
-rw-r--r--db/matcher.h13
-rw-r--r--db/queryutil.cpp3
-rw-r--r--jstests/mod1.js16
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" );
+