Skip to content

Commit

Permalink
arrays match themselves in queryies SERVER-146
Browse files Browse the repository at this point in the history
  • Loading branch information
erh committed Oct 9, 2009
1 parent e6069e4 commit 0ca3016
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 14 deletions.
6 changes: 5 additions & 1 deletion db/matcher.cpp
Expand Up @@ -93,7 +93,7 @@ namespace mongo {
/* _jsobj - the query pattern
*/
JSMatcher::JSMatcher(const BSONObj &_jsobj, const BSONObj &constrainIndexKey) :
where(0), jsobj(_jsobj), haveSize(), all(), nRegex(0){
where(0), jsobj(_jsobj), haveSize(), all(), hasArray(0), nRegex(0){

BSONObjIterator i(jsobj);
while ( i.moreWithEOO() ) {
Expand Down Expand Up @@ -253,6 +253,10 @@ namespace mongo {
if ( ok )
continue;
}

if ( e.type() == Array ){
hasArray = true;
}

// normal, simple case e.g. { a : "foo" }
addBasic(e, BSONObj::Equality);
Expand Down
3 changes: 2 additions & 1 deletion db/matcher.h
Expand Up @@ -132,7 +132,7 @@ namespace mongo {
*/
bool matches(const BSONObj& j, bool *deep = 0);

bool keyMatch() const { return !all && !haveSize; }
bool keyMatch() const { return !all && !haveSize && !hasArray; }
private:
void addBasic(const BSONElement &e, int c) {
// TODO May want to selectively ignore these element types based on op type.
Expand All @@ -151,6 +151,7 @@ namespace mongo {
// int n; // # of basicmatcher items
bool haveSize;
bool all;
bool hasArray;

RegexMatcher regexs[4];
int nRegex;
Expand Down
23 changes: 18 additions & 5 deletions db/queryutil.cpp
Expand Up @@ -31,12 +31,25 @@ namespace mongo {
BSONObjIterator i( e.embeddedObject() );
while( i.more() )
vals.insert( i.next() );
for( set< BSONElement, element_lt >::const_iterator i = vals.begin(); i != vals.end(); ++i ) {
FieldInterval equalityInterval;
equalityInterval.lower_.bound_ = equalityInterval.upper_.bound_ = *i;
equalityInterval.lower_.inclusive_ = equalityInterval.upper_.inclusive_ = true;
intervals_.push_back( equalityInterval );

for( set< BSONElement, element_lt >::const_iterator i = vals.begin(); i != vals.end(); ++i )
intervals_.push_back( FieldInterval(*i) );

return;
}

if ( e.type() == Array && e.getGtLtOp() == BSONObj::Equality ){

intervals_.push_back( FieldInterval(e) );

const BSONElement& temp = e.embeddedObject().firstElement();
if ( ! temp.eoo() ){
if ( temp < e )
intervals_.insert( intervals_.begin() , temp );
else
intervals_.push_back( FieldInterval(temp) );
}

return;
}

Expand Down
5 changes: 5 additions & 0 deletions db/queryutil.h
Expand Up @@ -32,6 +32,11 @@ namespace mongo {
};

struct FieldInterval {
FieldInterval(){}
FieldInterval( const BSONElement& e ){
lower_.bound_ = upper_.bound_ = e;
lower_.inclusive_ = upper_.inclusive_ = true;
}
FieldBound lower_;
FieldBound upper_;
bool valid() const {
Expand Down
7 changes: 4 additions & 3 deletions dbtests/querytests.cpp
Expand Up @@ -486,7 +486,8 @@ namespace QueryTests {
client().insert( ns, fromjson( "{a:[1,2,3]}" ) );
ASSERT( client().query( ns, Query( "{a:[1,2,3]}" ) )->more() );
client().ensureIndex( ns, BSON( "a" << 1 ) );
//ASSERT( client().query( ns, Query( "{a:[1,2,3]}" ).hint( BSON( "a" << 1 ) ) )->more() ); // TODO: turn this back on when SERVER-146 is fixed
ASSERT( client().query( ns, Query( "{a:{$in:[1,[1,2,3]]}}" ).hint( BSON( "a" << 1 ) ) )->more() );
ASSERT( client().query( ns, Query( "{a:[1,2,3]}" ).hint( BSON( "a" << 1 ) ) )->more() ); // SERVER-146
}
};

Expand All @@ -500,7 +501,7 @@ namespace QueryTests {
client().insert( ns, fromjson( "{a:[[1],2]}" ) );
check( "$natural" );
client().ensureIndex( ns, BSON( "a" << 1 ) );
//check( "a" ); // TODO: turn this back on when SERVER-146 is fixed
check( "a" ); // SERVER-146
}
private:
void check( const string &hintField ) {
Expand All @@ -522,7 +523,7 @@ namespace QueryTests {
client().insert( ns, fromjson( "{'_id':1,a:[1]}" ) );
client().insert( ns, fromjson( "{'_id':2,a:[[1]]}" ) );
client().ensureIndex( ns, BSON( "a" << 1 ) );
ASSERT_EQUALS( 2, client().query( ns, Query( "{a:[1]}" ).hint( BSON( "a" << 1 ) ) )->next().getIntField( "_id" ) );
ASSERT_EQUALS( 1, client().query( ns, Query( "{a:[1]}" ).hint( BSON( "a" << 1 ) ) )->next().getIntField( "_id" ) );
}
};

Expand Down
2 changes: 1 addition & 1 deletion jstests/array1.js
Expand Up @@ -11,4 +11,4 @@ delete x._id;
assert.eq( 2 , t.find( x ).count() , "B" );

t.ensureIndex( { a : 1 } );
//assert.eq( 2 , t.find( x ).count() , "C" ); // TODO turn this on
assert.eq( 2 , t.find( x ).count() , "C" ); // TODO SERVER-146
6 changes: 3 additions & 3 deletions jstests/index_check2.js
Expand Up @@ -24,9 +24,9 @@ assert.eq( 120 , t.find( q1 ).itcount() , "q1 a");
assert.eq( 120 , t.find( q2 ).itcount() , "q2 a" );
assert.eq( 60 , t.find( q3 ).itcount() , "q3 a");

assert.eq( "BtreeCursor tags_1" , t.find( q1 ).explain().cursor );
assert.eq( "BtreeCursor tags_1" , t.find( q2 ).explain().cursor );
assert.eq( "BtreeCursor tags_1" , t.find( q3 ).explain().cursor );
assert.eq( "BtreeCursor tags_1" , t.find( q1 ).explain().cursor , "e1" );
assert.eq( "BtreeCursor tags_1" , t.find( q2 ).explain().cursor , "e2" );
assert.eq( "BtreeCursor tags_1" , t.find( q3 ).explain().cursor , "e3" );

scanned1 = t.find(q1).explain().nscanned;
scanned2 = t.find(q2).explain().nscanned;
Expand Down

0 comments on commit 0ca3016

Please sign in to comment.