javascript - Updating a Nested Array with MongoDB -
i trying update value in nested array can't work.
my object this
{ "_id": { "$oid": "1" }, "array1": [ { "_id": "12", "array2": [ { "_id": "123", "answeredby": [], }, { "_id": "124", "answeredby": [], } ], } ] } i need push value "answeredby" array.
in below example, tried pushing "success" string "answeredby" array of "123 _id" object not work.
callback = function(err,value){ if(err){ res.send(err); }else{ res.send(value); } }; conditions = { "_id": 1, "array1._id": 12, "array2._id": 123 }; updates = { $push: { "array2.$.answeredby": "success" } }; options = { upsert: true }; model.update(conditions, updates, options, callback); i found link, answer says should use object structure instead of array's. cannot applied in situation. need object nested in arrays
it great if can me out here. i've been spending hours figure out.
thank in advance!
general scope , explanation
there few things wrong doing here. firstly query conditions. referring several _id values should not need to, , @ least 1 of not on top level.
in order "nested" value , presuming _id value unique , not appear in other document, query form should this:
model.update( { "array1.array2._id": "123" }, { "$push": { "array1.0.array2.$.answeredby": "success" } }, function(err,numaffected) { // result in here } ); now work, fluke there reasons why should not work you.
the important reading in official documentation positional $ operator under subject of "nested arrays". says is:
the positional $ operator cannot used queries traverse more 1 array, such queries traverse arrays nested within other arrays, because replacement $ placeholder single value
specifically means element matched , returned in positional placeholder value of index first matching array. means in case matching index on "top" level array.
so if @ query notation shown, have "hardcoded" first ( or 0 index ) position in top level array, , happens matching element within "array2" 0 index entry.
to demonstrate can change matching _id value "124" , result $push new entry onto element _id "123" both in 0 index entry of "array1" , value returned placeholder.
so general problem nesting arrays. remove 1 of levels , still able $push correct element in "top" array, there still multiple levels.
try avoid nesting arrays run update problems shown.
the general case "flatten" things "think" "levels" , make theses "attributes" on final detail items. example, "flattened" form of structure in question should like:
{ "answers": [ { "by": "success", "type2": "123", "type1": "12" } ] } or when accepting inner array $push only, , never updated:
{ "array": [ { "type1": "12", "type2": "123", "answeredby": ["success"] }, { "type1": "12", "type2": "124", "answeredby": [] } ] } which both lend atomic updates within scope of positional $ operator
mongodb 3.6 , above
from mongodb 3.6 there new features available work nested arrays. uses positional filtered $[<identifier>] syntax in order match specific elements , apply different conditions through arrayfilters in update statement:
model.update( { "_id": 1, "array1": { "$elemmatch": { "_id": "12","array2._id": "123" } } }, { "$push": { "array1.$[outer].array2.$[inner].answeredby": "success" } }, { "arrayfilters": [{ "outer._id": "12" },{ "inner._id": "123" }] } ) the "arrayfilters" passed options .update() or .updateone(), .updatemany(), .findoneandupdate() or .bulkwrite() method specifies conditions match on identifier given in update statement. elements match condition given updated.
because structure "nested", use "multiple filters" specified "array" of filter definitions shown. marked "identifier" used in matching against positional filtered $[<identifier>] syntax used in update block of statement. in case inner , outer identifiers used each condition specified nested chain.
this new expansion makes update of nested array content possible, not practicality of "querying" such data, same caveats apply explained earlier.
you typically "mean" express "attributes", if brain thinks "nesting", it's reaction how believe "previous relational parts" come together. in reality need more denormalization.
also see how update multiple array elements in mongodb, since these new update operators match , update "multiple array elements" rather first, has been previous action of positional updates.
note ironically, since specified in "options" argument
.update(), methods, syntax compatible recent release driver versions.however not true of
mongoshell, since way method implemented there ( "ironically backward compatibility" )arrayfiltersargument not recognized , removed internal method parses options in order deliver "backward compatibility" prior mongodb server versions , "legacy".update()api call syntax.so if want use command in
mongoshell or other "shell based" products ( notably robo 3t ) need latest version either development branch or production release of 3.6 or greater.
see positional $[] updates "multiple array elements" without applying specified conditions , applies all elements in array desired action.
Comments
Post a Comment