diff options
author | Eliot Horowitz <eliot@10gen.com> | 2010-05-05 22:52:51 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2010-05-05 22:53:59 -0400 |
commit | c1007834f6c7d724e824a91c60ab1e2aef2e07c9 (patch) | |
tree | c764fbe407edd0ed78c6e95771e3763c43a071ba | |
parent | 19672f06efbb3edf279e175b2fdca2469a7fbeb1 (diff) | |
download | mongo-c1007834f6c7d724e824a91c60ab1e2aef2e07c9.tar.gz |
fix updates on indexes fields when using array offsets SERVER-1093
-rw-r--r-- | db/update.h | 48 | ||||
-rw-r--r-- | jstests/index_arr2.js | 51 |
2 files changed, 97 insertions, 2 deletions
diff --git a/db/update.h b/db/update.h index 5d20114fe97..3c4daabaeae 100644 --- a/db/update.h +++ b/db/update.h @@ -100,12 +100,13 @@ namespace mongo { } } - bool isIndexed( const set<string>& idxKeys ) const { + static bool isIndexed( const string& fullName , const set<string>& idxKeys ){ + const char * fieldName = fullName.c_str(); // check if there is an index key that is a parent of mod for( const char *dot = strchr( fieldName, '.' ); dot; dot = strchr( dot + 1, '.' ) ) if ( idxKeys.count( string( fieldName, dot - fieldName ) ) ) return true; - string fullName = fieldName; + // check if there is an index key equal to mod if ( idxKeys.count(fullName) ) return true; @@ -113,6 +114,49 @@ namespace mongo { set< string >::const_iterator j = idxKeys.upper_bound( fullName ); if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[fullName.size()] == '.' ) return true; + + return false; + } + + bool isIndexed( const set<string>& idxKeys ) const { + string fullName = fieldName; + + if ( isIndexed( fullName , idxKeys ) ) + return true; + + if ( strstr( fieldName , "." ) ){ + // check for a.0.1 + StringBuilder buf( fullName.size() + 1 ); + for ( size_t i=0; i<fullName.size(); i++ ){ + char c = fullName[i]; + buf << c; + + if ( c != '.' ) + continue; + + if ( ! isdigit( fullName[i+1] ) ) + continue; + + bool possible = true; + size_t j=i+2; + for ( ; j<fullName.size(); j++ ){ + char d = fullName[j]; + if ( d == '.' ) + break; + if ( isdigit( d ) ) + continue; + possible = false; + break; + } + + if ( possible ) + i = j; + } + string x = buf.str(); + if ( isIndexed( x , idxKeys ) ) + return true; + } + return false; } diff --git a/jstests/index_arr2.js b/jstests/index_arr2.js new file mode 100644 index 00000000000..21a511b8485 --- /dev/null +++ b/jstests/index_arr2.js @@ -0,0 +1,51 @@ +NUM = 20; +M = 5; + +t = db.xxx; + +function test( withIndex ){ + t.drop(); + + // insert a bunch of items to force queries to use the index. + newObject = { + _id : 1, + a : [ + { b : { c : 1 } } + ] + } + + now = (new Date()).getTime() / 1000; + for (created = now - NUM; created <= now; created++ ) { + newObject['created'] = created; + t.insert(newObject); + newObject['_id'] ++; + } + + // change the last M items. + query = { + 'created' : { '$gte' : now - M } + } + + Z = t.find( query ).count(); + + if ( withIndex ){ + //t.ensureIndex( { 'a.b.c' : 1, 'created' : -1 } ) + //t.ensureIndex( { created : -1 } ) + t.ensureIndex( { 'a.b.c' : 1 } , { name : "x" } ) + } + + t.update(query, { '$set' : { "a.0.b.c" : 0 } } , false , true ) + assert.eq( Z , db.getLastErrorObj().n , "num updated withIndex:" + withIndex ); + + // now see how many were actually updated. + query['a.b.c'] = 0; + + count = t.count(query); + + assert.eq( Z , count , "count after withIndex:" + withIndex ); +} + +test( false ) +test( true ); + + |