From 7ba4140d5c29823adeb1f5ea3cea1a94b65252af Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 25 Mar 2009 14:47:04 -0400 Subject: [PATCH] Add $size query option --- db/jsobj.cpp | 2 ++ db/matcher.cpp | 22 ++++++++++++++++++++++ db/matcher.h | 3 ++- dbtests/matchertests.cpp | 11 +++++++++++ s/shardkey.cpp | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/db/jsobj.cpp b/db/jsobj.cpp index e6588dc73cf..6622c040936 100644 --- a/db/jsobj.cpp +++ b/db/jsobj.cpp @@ -407,6 +407,8 @@ namespace mongo { } else if ( fn[1] == 'i' && fn[2] == 'n' && fn[3] == 0 ) return JSMatcher::opIN; + else if ( fn[1] == 's' && fn[2] == 'i' && fn[3] == 'z' && fn[4] == 'e' && fn[5] == 0 ) + return JSMatcher::opSIZE; } return JSMatcher::Equality; } diff --git a/db/matcher.cpp b/db/matcher.cpp index dbf407d33e2..a74c4b125ac 100644 --- a/db/matcher.cpp +++ b/db/matcher.cpp @@ -258,6 +258,14 @@ namespace mongo { addBasic(e, opIN); // e not actually used at the moment for $in ok = true; } + else if ( fn[1] == 's' && fn[2] == 'i' && fn[3] == 'z' && fn[4] == 'e' ) { + uassert( "$size must be a number", fe.isNumber() ); + BSONObjBuilder *b = new BSONObjBuilder(); + builders[nBuilders++] = b; + b->appendAs(fe, e.fieldName()); + addBasic(b->done().firstElement(), opSIZE); + ok = true; + } else uassert("invalid $operator", false); } @@ -289,6 +297,20 @@ namespace mongo { return c; } + if ( op == opSIZE ) { + if ( l.type() != Array ) + return 0; + int count = 0; + BSONObjIterator i( l.embeddedObject() ); + while( i.more() ) { + BSONElement e = i.next(); + if ( e.eoo() ) + break; + ++count; + } + return count == r.number(); + } + /* 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 6fb621f6dab..667c061d3c9 100644 --- a/db/matcher.h +++ b/db/matcher.h @@ -86,7 +86,8 @@ namespace mongo { GTE = 0x6, GT = 0x4, opIN = 0x8, // { x : { $in : [1,2,3] } } - NE = 0x9 + NE = 0x9, + opSIZE = 0x10 }; static int opDirection(int op) { diff --git a/dbtests/matchertests.cpp b/dbtests/matchertests.cpp index ef15905e784..3de53a7c753 100644 --- a/dbtests/matchertests.cpp +++ b/dbtests/matchertests.cpp @@ -64,6 +64,16 @@ namespace MatcherTests { } }; + class Size { + public: + void run() { + JSMatcher m( fromjson( "{a:{$size:4}}" ) ); + ASSERT( m.matches( fromjson( "{a:[1,2,3,4]}" ) ) ); + ASSERT( !m.matches( fromjson( "{a:[1,2,3]}" ) ) ); + ASSERT( !m.matches( fromjson( "{a:[1,2,3,'a','b']}" ) ) ); + } + }; + class All : public UnitTest::Suite { public: All() { @@ -71,6 +81,7 @@ namespace MatcherTests { add< DoubleEqual >(); add< MixedNumericEqual >(); add< MixedNumericGt >(); + add< Size >(); } }; diff --git a/s/shardkey.cpp b/s/shardkey.cpp index 67cf4088e4e..80e5f4a6d44 100644 --- a/s/shardkey.cpp +++ b/s/shardkey.cpp @@ -383,6 +383,7 @@ namespace mongo { break; case JSMatcher::opIN: case JSMatcher::NE: + case JSMatcher::opSIZE: massert("not implemented yet relevant()", false); case JSMatcher::Equality: goto normal;