0

I have a rooms model. Within it is an array of User's which has its own model.

Each user has a bunch of different attributes, some of them being boolean. Knowing the ID of the specific room and the specific user, I am attempting to change the boolean value within a specific User element within the sub array like this:

Room.findOne({_id: roomId, "users" : user}, { "$set" : { mutedAudio : false}})
        .then(doc => {
            console.log("Unmuted audio");
            res.json(doc)
            io.in(roomId).emit('userchange');
        })
        .catch(err => {
            console.log(err);
        })

(I'm using a user model instead of a user ID for seeking the user within the sub array. Could not get ID to work but can fetch object by comparing it to itself entirely.)

I get the error:

MongoError: Unsupported projection option: $set: { mutedAudio: true }

Anyone know the answer to this?

Thank you.

EDIT:

const RoomSchema = new Schema({
    owner: {
        id: {
            type: String
        },
        username: {
            type: String
        }
    },
    roomname: {
        type: String,
        required: true
    },
    category: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: false
    },
    users: [UserSchema],
    messages: [{
        username: {
            type: String
        },
        message: {
            type: String
        },
        time: {
            type: String
        }
    }],
    date: {
        type: Date,
        default: Date.now
    }
});

const UserSchema = new Schema({
    id: {
        type: String
    },
    username: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    avatar: {
        type: String
    },
    date: {
        type: Date,
        default: Date.now
    },
    micEnabled: {
        type: Boolean,
        default: false
    },
    mutedAudio: {
        type: Boolean,
        default: true
    }
});
BURGERFLIPPER101
  • 1,231
  • 4
  • 24
  • 41

1 Answers1

1

Model.findOne() takes 4 parameters, the second being "optional fields to return", that's why you're getting the error, mongoose is trying to select fields to return according to $set: { mutedAudio: true } which is being passed as a second parameter (therefore considered to be a projection option).
Use Model.findOneAndUpdate() which takes an update object as a second parameter, along with the positional operator $.

  Room.findOneAndUpdate(
    { "_id": roomId, "users._id": userID },{ "$set": { "users.$.mutedAudio": false } } )
      .then(doc => {
         console.log("Unmuted audio");
         res.json(doc)
         io.in(roomId).emit('userchange');
        })
        .catch(err => {
            console.log(err);
        })

Original answer by @Neil Lunn in Mongoose find/update subdocument

Moad Ennagi
  • 1,058
  • 1
  • 11
  • 19
  • Thank you Moad. It doesn't throw me an error anymore and the console log "unmuted audio" works and my socket sends a message as if the change was a success, yet when I check the value in my Mongodb instance nothing has changed. My Redux state on my react client doesn't pick up any changes either. Would you have any clue what could be going wrong? – BURGERFLIPPER101 Apr 08 '19 at 20:23
  • 1
    Could your provide code for your schemas (Room and User) ? – Moad Ennagi Apr 08 '19 at 20:33
  • I've added them to the main post – BURGERFLIPPER101 Apr 08 '19 at 20:37
  • Your query actually returns the `Room` document, you are trying to set `mutedAudio` on the `Room` document. have a look at this question https://stackoverflow.com/questions/26156687/mongoose-find-update-subdocument/26157458 – Asaf Aviv Apr 08 '19 at 21:08