$unset subdocument where the key is a string


#1

Hey guys,

I’m trying to $unset a subdocument from the roles object in the following document:

{
    "_id" : "9PKqJ948LzFZGkHhz",
    "roles": {
        "abc:def": ["foo", "bar"],
        "ghj:klm": ["foo", "bar"]
}

Via mongo shell the following statement works as expected:

db.getCollection('users').update({_id: '9PKqJ948LzFZGkHhz'}, {$unset: {"roles.abc:def": 1}})

If I try the following code in the meteor server shell, it removes the whole “roles” object.
“abc:def” must be passed as a dnynamic string.
Of course I could readin the whole roles object and write a new one without this key, but I would like to know if this is doable with $unset?

let unsetObj = {
  roles: {}
};
unsetObj.roles["abc:def"] = 1;

Meteor.users.update({
  _id: '9PKqJ948LzFZGkHhz',
}, {
  $unset: unsetObj
});

#2

Mongo requires dot notation when using $unset, so adjust your $unset value accordingly.

...
Meteor.users.update({
  _id: '9PKqJ948LzFZGkHhz',
}, {
  $unset: { 
    'roles.abc:def': 1 
  }
});
...

#3

Yeah, but “abc” and “def” are strings which I need to set before I fire the query.


#4

Right, but you can always just convert the $unset value into dot notation dynamically. Quick example:

const unsetTheseRoles = [
  'abc:def',
  'ghi:jkl',  
  ...
];

let unsetObject = {};
unsetTheseRoles.forEach((role) => {
  unsetObject[`roles.${role}`] = 1;
});

Meteor.users.update({
  _id: '9PKqJ948LzFZGkHhz',
}, {
  $unset: unsetObject
});