mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 17:10:48 +01:00
$addToSet mostly working SERVER-176
This commit is contained in:
parent
ca42b6de8a
commit
556c5a6d7d
@ -27,7 +27,7 @@
|
||||
namespace mongo {
|
||||
|
||||
const char* Mod::modNames[] = { "$inc", "$set", "$push", "$pushAll", "$pull", "$pullAll" , "$pop", "$unset" ,
|
||||
"$bitand" , "$bitor" , "$bit" };
|
||||
"$bitand" , "$bitor" , "$bit" , "$addToSet" };
|
||||
unsigned Mod::modNamesNum = sizeof(Mod::modNames)/sizeof(char*);
|
||||
|
||||
bool Mod::_pullElementMatch( BSONElement& toMatch ) const {
|
||||
@ -85,7 +85,7 @@ namespace mongo {
|
||||
//Explicit NOOP
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PUSH: {
|
||||
uassert( 10131 , "$push can only be applied to an array" , in.type() == Array );
|
||||
BSONObjBuilder bb( b.subarrayStart( shortFieldName ) );
|
||||
@ -102,6 +102,30 @@ namespace mongo {
|
||||
bb.done();
|
||||
break;
|
||||
}
|
||||
|
||||
case ADDTOSET: {
|
||||
uassert( 12592 , "$addToSet can only be applied to an array" , in.type() == Array );
|
||||
BSONObjBuilder bb( b.subarrayStart( shortFieldName ) );
|
||||
BSONObjIterator i( in.embeddedObject() );
|
||||
|
||||
bool found = false;
|
||||
|
||||
int n=0;
|
||||
while ( i.more() ){
|
||||
BSONElement cur = i.next();
|
||||
bb.append( cur );
|
||||
n++;
|
||||
if ( elt.woCompare( cur , false ) == 0 )
|
||||
found = true;
|
||||
}
|
||||
|
||||
if ( ! found )
|
||||
bb.appendAs( elt , bb.numStr( n ) );
|
||||
bb.done();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
case PUSH_ALL: {
|
||||
uassert( 10132 , "$pushAll can only be applied to an array" , in.type() == Array );
|
||||
@ -274,15 +298,18 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Mod::SET:
|
||||
mss->amIInPlacePossible( m.elt.type() == e.type() &&
|
||||
m.elt.valuesize() == e.valuesize() );
|
||||
break;
|
||||
|
||||
case Mod::PUSH:
|
||||
case Mod::PUSH_ALL:
|
||||
uassert( 10141 , "Cannot apply $push/$pushAll modifier to non-array", e.type() == Array || e.eoo() );
|
||||
mss->amIInPlacePossible( false );
|
||||
break;
|
||||
|
||||
case Mod::PULL:
|
||||
case Mod::PULL_ALL: {
|
||||
uassert( 10142 , "Cannot apply $pull/$pullAll modifier to non-array", e.type() == Array || e.eoo() );
|
||||
@ -304,11 +331,29 @@ namespace mongo {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Mod::POP: {
|
||||
uassert( 10143 , "Cannot apply $pop modifier to non-array", e.type() == Array || e.eoo() );
|
||||
mss->amIInPlacePossible( e.embeddedObject().isEmpty() );
|
||||
break;
|
||||
}
|
||||
|
||||
case Mod::ADDTOSET: {
|
||||
uassert( 12591 , "Cannot apply $addToSet modifier to non-array", e.type() == Array || e.eoo() );
|
||||
|
||||
BSONObjIterator i( e.embeddedObject() );
|
||||
bool found = false;
|
||||
while( i.more() ) {
|
||||
BSONElement arrI = i.next();
|
||||
if ( arrI.woCompare( m.elt , false ) == 0 ){
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mss->amIInPlacePossible( found );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// mods we don't know about shouldn't be done in place
|
||||
mss->amIInPlacePossible( false );
|
||||
@ -325,6 +370,7 @@ namespace mongo {
|
||||
case Mod::UNSET:
|
||||
case Mod::PULL:
|
||||
case Mod::PULL_ALL:
|
||||
case Mod::ADDTOSET:
|
||||
// this should have been handled by prepare
|
||||
break;
|
||||
|
||||
|
14
db/update.h
14
db/update.h
@ -32,8 +32,8 @@ namespace mongo {
|
||||
*/
|
||||
struct Mod {
|
||||
// See opFromStr below
|
||||
// 0 1 2 3 4 5 6 7 8 9 10
|
||||
enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BITAND, BITOR , BIT } op;
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BITAND, BITOR , BIT , ADDTOSET } op;
|
||||
|
||||
static const char* modNames[];
|
||||
static unsigned modNamesNum;
|
||||
@ -160,7 +160,7 @@ namespace mongo {
|
||||
|
||||
return compareDottedFieldNames( m->first, p->first.c_str() );
|
||||
}
|
||||
|
||||
|
||||
bool mayAddEmbedded( map< string, BSONElement > &existing, string right ) {
|
||||
for( string left = EmbeddedBuilder::splitDot( right );
|
||||
left.length() > 0 && left[ left.length() - 1 ] != '.';
|
||||
@ -220,6 +220,14 @@ namespace mongo {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
if ( fn[2] == 'd' && fn[3] == 'd' ){
|
||||
// add
|
||||
if ( fn[4] == 'T' && fn[5] == 'o' && fn[6] == 'S' && fn[7] == 'e' && fn[8] == 't' && fn[9] == 0 )
|
||||
return Mod::ADDTOSET;
|
||||
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
uassert( 10161 , "Invalid modifier specified " + string( fn ), false );
|
||||
|
15
jstests/update_addToSet.js
Normal file
15
jstests/update_addToSet.js
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
t = db.update_addToSet1;
|
||||
t.drop();
|
||||
|
||||
o = { _id : 1 , a : [ 2 , 1 ] }
|
||||
t.insert( o );
|
||||
|
||||
assert.eq( o , t.findOne() , "A1" );
|
||||
|
||||
t.update( {} , { $addToSet : { a : 3 } } );
|
||||
o.a.push( 3 );
|
||||
assert.eq( o , t.findOne() , "A2" );
|
||||
|
||||
t.update( {} , { $addToSet : { a : 3 } } );
|
||||
assert.eq( o , t.findOne() , "A3" );
|
Loading…
Reference in New Issue
Block a user