Descubrí que el comando $pull tampoco me funciona a menos que incluya la devolución de llamada en la lista de argumentos.
En mi situación, este formato no funcionó:
UserAlerts.findOneAndUpdate({userId: userId}, {$pull: {alerts: {_id: alertId}}});
Pero este formato hizo:
UserAlerts.findOneAndUpdate({userId: userId}, {$pull: {alerts: {_id: alertId}}}, function(err, data){
console.log(err, data);
});
De acuerdo con la documentación, parece que ambos deberían funcionar, pero no lo hacen. El motivo es que la primera forma requiere que llame a .exec() en el objeto devuelto, mientras que la versión de devolución de llamada llama a exec() automáticamente. También me causó cierta confusión.
Así que necesitas hacer algo como esto:
UserAlerts.findOneAndUpdate({userId: userId}, {$pull: {alerts: {_id: alertId}}}).exec();