1

"mongoose": "^5.12.2"

I have a schema named User. This schema has a field named "rol" of type string[] for a multiple rol application (User, Admin, Freetour, BarOwner, etc).

The function that adds a rol to a user is defined like this:

public addRolToUser = (idUser:string, newRol:string):Promise<IUser> => {
        try{
            return new Promise<IUser>((resolve, reject) => {
               User.findByIdAndUpdate(idUser, { addToSet: {rol:newRol} }, {new:true}).then(user => { 
                   return resolve(user);
                }).catch(err => {
                   return reject(err);
                });
            });
        }catch (e) {
            throw e;
        }
      };

However this doesn´t update the "rol" field of the user. The following function should add the rol "FreeTour" to the user with the id returned by "petition.user".

public acceptPetition = async(req:Request, res:Response) => {
        try{
            return this.solFreeTourService.acceptPetition(req.body.idPetition).then(petition => {
 
            let acceptPromise = new Promise((resolve, reject) => {

                // Here I´m invoking the addRolToUser function
                return this.userService.addRolToUser(petition.user, "FREETOUR").then((resUser)=>{

                // resUser here has the same value for the "rol" field, didn´t get updated.                    
                return resolve(petition);
                }).catch(err=>{
                    return reject(err);
                })
            })
            return acceptPromise.then(petition=>{
                return res.status(200).json({petition});
            }).catch(e=>{
                res.status(400).json({ status: 400, message: "There has been an error." });
            });
            })
        }catch (e) {
            res.status(400).json({ status: 400, message: "There has been an error." });
        }
    } 

I don't want repeated values in the "rol" array, hence pushing is not an option.

What am I doing wrong?

Ricard0-MT
  • 11
  • 3
  • Try looking at this article https://stackoverflow.com/questions/33049707/push-items-into-mongo-array-via-mongoose – scovic May 16 '21 at 23:26
  • 1
    Does this answer your question? [Push items into mongo array via mongoose](https://stackoverflow.com/questions/33049707/push-items-into-mongo-array-via-mongoose) – Tushar Gupta - curioustushar May 17 '21 at 01:55
  • None of the solutions in that article worked. I even added a callback function, which resulted in no errors and returned the unchanged document. I then checked the schema on MongoDB Compass, and found the document with no update on it. – Ricard0-MT May 17 '21 at 06:39
  • shouldn't you use `User.findByIdAndUpdate(idUser, { $push: {rol:newRol} }, {new:true})` as you're adding an element to an array?... plus, I stopped using `User.findByIdAndUpdate` some time ago in prol of `User.updateOne()` as recommended... – balexandre May 17 '21 at 06:58
  • @balexandre note that I don't want repeated values in the array, hence pushing alone is not a solution: I'd only push a value if it's not already in the array (which is basically what "addToSet" should be doing here). I'll replace findByIdAndUpdate with updateOne and try my luck. Will get by to you – Ricard0-MT May 17 '21 at 08:26
  • @Ricard0-MT true, you should use addToSet but you should write as `$addToSet` (with the `$` as prefix as it's a MongoDB command... could that be the culprit? – balexandre May 17 '21 at 08:38
  • @balexandre Nop, tried before with the prefix "$" and got a compilation error. – Ricard0-MT May 17 '21 at 09:19

1 Answers1

0

first of all, Welcome to StackOverflow!

I have to assume that you might have something not working well together as you say you're using Mongoose and for such I've made a very simple project that you can look into in GitHub

where I create a very simple schema

const UserSchema = mongoose.Schema({
    role: [{
        type: String
    }],
    guid: {
        type: String,
        required: true
    },
});

and then make use of the Mongoose API to create, update and find the user

const guid = uuidv4();

// create user
await UserModel.create({ guid });
log('user created');

["admin", "user", "admin"].forEach(async (role) => {
    // add role to user
    await UserModel.updateOne({ guid }, { $addToSet: { role } });
    log(`user role updated with ${role}`);
});

// read user
const newUser = await UserModel.where({ guid }).findOne();
log(JSON.stringify(newUser, null, 2));

and the output is the expected one

user created
user role updated with admin
user role updated with user
user role updated with admin
{
  "role": [
    "admin",
    "user"
  ],
  "_id": "60a2397b1c488d4968d6ed46",
  "guid": "26ccacbf-ddbc-4cbf-ac69-2da3235e156b",
  "__v": 0
}

fell free to look into the source code, clone, run, and test, and notice that I'm using in fact the Mongo command as $addToSet

balexandre
  • 73,608
  • 45
  • 233
  • 342