e.g. for the following example setup.
var user_schema = new Schema ( {
name : String,
sessions : [
new Schema ( { latest : Boolean, created : { type : Date, default : Date.now } } );
]
} );
var User = mongoose. model ( user_schema ),
ash = new User();
ash.name = 'ashheskes';
ash.sessions.push ( [ { latest : false }, { latest : true } ] );
// We need to save the user first because the sessions array has only just been created anyway.
ash.save ( function ( error, ash ) {
User.findOne ( ash.id, function ( error ) {
/* Add a new item to the array */
var new_session_index = ash sessions.push ( { latest : true } );
/* Loop through all existing sessions and unmark them as latest */
ash.sessions.forEach ( function ( session, i ) {
if ( i === new_session_index ) return;
else session.latest = false;
} );
/* Causes the entire array to be marked modified instead of the individual paths. */
console.log ( ash.isModified ( 'sessions' ) ); // > true
} );
} );
In most cases this wouldn't be a problem because the entire array of nested schemas has been returned.
However for following example using a $slice projector on the array. It causes only the content returned to be saved, discarding all other data stored in the array in the DB.
/* Find `ash` but only return the last session in the array. */
User. findOne ( ash. id, { sessions : { $slice : -1 } }, function ( error, ash ) {
var new_session_index = ash.sessions.push ( { latest : true } ) - 1;
/* Loop through all existing sessions and unmark them as latest */
ash.sessions.forEach ( function ( session, i ) {
if ( i === new_session_index ) return;
else session.latest = false;
} );
ash.save ( function ( error, ash ) {
/*
sessions should be 3, but the entire array in the DB
has been overwritten by the array on the client.
*/
console.log ( ash.sessions.length ); // > 2
} );
} );
I've tried using a different approach with user.set(). However this seems to completely overwrite the document in the array with a basic Object and causes an error when saving.
/* Find `ash` but only return the last session in the array. */
User. findOne ( ash. id, { sessions : { $slice : -1 } }, function ( error, ash ) {
var new_session_index = ash.sessions.push ( { latest : true } ) - 1;
/* Loop through all existing sessions and unmark them as latest */
ash.sessions.forEach ( function ( session, i ) {
if ( i === new_session_index ) return;
else ash.set ( 'sessions.' + i + '.latest', true );
} );
/* Subdocuments converted to `Objects` */
console.log ( ash.sessions ) // > [Object, Object, subdocument]
/* All other data from the subdoc's is lost. */
console.log ( ash.sessions [ 0 ] ) // > { latest : false }
/*
An internal error occurs when mongoose tries to call save
on subdocs that got converted to standard `Objects`.
*/
ash.save(); // > Error : #Object has no method save.
} );
e.g. for the following example setup.
In most cases this wouldn't be a problem because the entire array of nested schemas has been returned.
However for following example using a
$sliceprojector on the array. It causes only the content returned to be saved, discarding all other data stored in the array in the DB.I've tried using a different approach with
user.set(). However this seems to completely overwrite the document in the array with a basic Object and causes an error when saving.