Удалить ключ из документа MongoDB с помощью Mongoose


103

Я использую библиотеку Mongoose для доступа к MongoDB с помощью node.js

Есть ли способ удалить ключ из документа ? т.е. не просто установить значение null, а удалить его?

User.findOne({}, function(err, user){
  //correctly sets the key to null... but it's still present in the document
  user.key_to_delete = null;

  // doesn't seem to have any effect
  delete user.key_to_delete;

  user.save();
});

1
Я думал, что нашел, но после некоторых тестов: наверное, нет. Тем не менее, здесь есть хорошее обсуждение этой темы. groups.google.com/group/mongoose-orm/browse_thread/thread/…
Стивен,

LOL, да ладно, это был твой пост!
Стивен

Ответы:


168

В ранних версиях вам нужно было выпустить драйвер node-mongodb-native. У каждой модели есть объект коллекции, содержащий все методы, которые предлагает node-mongodb-native. Итак, вы можете выполнить рассматриваемое действие следующим образом:

User.collection.update({_id: user._id}, {$unset: {field: 1 }});

Начиная с версии 2.0 вы можете:

User.update({_id: user._id}, {$unset: {field: 1 }}, callback);

А начиная с версии 2.4, если у вас уже есть экземпляр модели, вы можете:

doc.field = undefined;
doc.save(callback);

Это было исправлено в Mongoose 2.X, поэтому вы можете не использовать коллекцию.
staackuser2

4
Либо используйте, User.update({ _id: id }, { $unset: { field: 1 }}, callback)либо, если у вас есть экземпляр документа, установите для пути значение undefined и затем сохраните его:doc.field = undefined; doc.save()
aaronheckmann

25
Обратите внимание: если вы пытаетесь удалить старое свойство, которое больше не определено в вашей схеме, вам необходимо сделать этоdoc.set('field', undefined)
evilcelery

3
как насчет удаления doc.field.foo?
chovy

28
@evilcelery doc.set('field', undefined)может быть недостаточно, поскольку строгий режим (по умолчанию) не позволяет устанавливать поля, которых больше нет в схеме. doc.set('field', undefined, { strict: false })работал нормально.
Александр Линк

56

Вы захотите сделать это:

User.findOne({}, function(err, user){
  user.key_to_delete = undefined;
  user.save();
});

3
Это просто установит для него значение null - а не то, о чем просит OP.
Ian Henry

25
Начиная с версии 2.4.0 установка ключа документа на undefined передаст $ unset на mongodb aaronheckmann.posterous.com/mongoose-240
Джеймс Мур,

30

Я использую мангуст, и использование любой из вышеперечисленных функций сделало меня необходимым. Функция компилируется без ошибок, но поле все равно остается.

user.set('key_to_delete', undefined, {strict: false} );

сделал трюк для меня.


Проголосование за этот полезный ответ, очень плохой @ alexander-link, не
дало

1
Спасибо за ответ, для меня другие решения не работали для объектов, вложенных в массивы!
BenSower

@BenSower Это тоже был мой случай. Только это решение сработало хорошо, потому что мне пришлось удалить поле с массивом после нахождения идентификатора конкретного документа
Луис,

Обратите внимание, что строка - это путь к ключу. Итак, если объект, который вы хотите удалить, является вложенным, вы должны указать к нему путь. Этот ответ решил мою проблему!
Bradyo

8

В синтаксисе mongo для удаления некоторого ключа вам нужно сделать следующее:

{ $unset : { field : 1} }

Похоже, у Мангуста то же самое.

редактировать

Посмотрите этот пример.


Можете ли вы уточнить этот ответ и привести пример кода, который относится к приведенному выше примеру кода?
Дэниел Бердсли,

извините, но я не знаю мангуста. Синтаксис выше - это синтаксис mongo, поэтому я полагаю, что драйвер для любого языка поддерживает это. Я нашел какой-то пример, проверьте это в своем ответе.
Эндрю Орсич 04

1

Может ли это быть побочной проблемой, например, с использованием

function (user)

вместо того

function(err, user)

для обратного вызова находки? Просто пытаюсь помочь с этим, так как у меня уже был случай.


1

Документ Mongoose НЕ является простым объектом javascript, поэтому вы не можете использовать оператор удаления (или unsetиз библиотеки lodash).

Ваши варианты - установить doc.path = null || undefined или использовать метод Document.toObject (), чтобы превратить документ мангуста в простой объект и оттуда использовать его как обычно. Подробнее читайте в mongoose api-ref: http://mongoosejs.com/docs/api.html#document_Document-toObject

Пример будет выглядеть примерно так:

User.findById(id, function(err, user) {
    if (err) return next(err);
    let userObject = user.toObject();
    // userObject is plain object
});

1

Пытаться:

User.findOne({}, function(err, user){
  // user.key_to_delete = null; X
  `user.key_to_delete = undefined;`

  delete user.key_to_delete;

  user.save();
});

0

проблема со всеми этими ответами в том, что они работают для одного поля. например, скажем, я хочу удалить все поля из моего документа, если они были пустой строкой "". Сначала вы должны проверить, является ли поле пустой строкой, поместите ее в $unset:

function unsetEmptyFields(updateData) {
  const $unset = {};
  Object.keys(updatedData).forEach((key) => {
    if (!updatedData[key]) {
      $unset[key] = 1;
      delete updatedData[key];
    }
  });
  updatedData.$unset = $unset;

  if (isEmpty(updatedData.$unset)) { delete updatedData.$unset; }

  return updatedData;
}

function updateUserModel(data){
const updatedData = UnsetEmptyFiled(data);

    const Id = "";
    User.findOneAndUpdate(
      { _id: Id },
      updatedData, { new: true },
    );
}

0

если вы хотите удалить ключ из коллекции, попробуйте этот метод. это сработало для меня

 db.getCollection('myDatabaseTestCollectionName').update({"FieldToDelete": {$exists: true}}, {$unset:{"FieldToDelete":1}}, false, true);

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.