Xóa khóa khỏi tài liệu MongoDB bằng Mongoose


102

Tôi đang sử dụng Thư viện Mongoose để truy cập MongoDB với node.js

Có cách nào để xóa khóa khỏi tài liệu không? tức là không chỉ đặt giá trị là null, nhưng loại bỏ nó?

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
Tôi nghĩ rằng tôi đã tìm thấy nó, nhưng sau một số thử nghiệm: có lẽ là không. Điều này có một số cuộc thảo luận tốt về chủ đề này. groups.google.com/group/mongoose-orm/browse_thread/thread/…
Stephen

LOL - Liên minh huyền thoại, tôi đoán đây là bài viết của bạn!
Stephen

Câu trả lời:


167

Trong các phiên bản đầu tiên, bạn sẽ cần phải thả xuống trình điều khiển node-mongodb-native. Mỗi mô hình có một đối tượng bộ sưu tập chứa tất cả các phương thức mà node-mongodb-native cung cấp. Vì vậy, bạn có thể thực hiện hành động được đề cập bằng cách:

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

Kể từ phiên bản 2.0, bạn có thể làm:

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

Và kể từ phiên bản 2.4, nếu bạn đã có một phiên bản của mô hình, bạn có thể làm:

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

Điều này đã được sửa trong Mongoose 2.X, vì vậy bạn có thể để bộ sưu tập ra ngoài.
staackuser 2

4
Hoặc sử dụng User.update({ _id: id }, { $unset: { field: 1 }}, callback)hoặc nếu bạn có một trường hợp tài liệu, thiết lập đường dẫn đến không xác định và sau đó lưu nó:doc.field = undefined; doc.save()
aaronheckmann

25
Chỉ cần một lưu ý rằng nếu bạn đang cố gắng để loại bỏ một tài sản cũ mà không còn được định nghĩa trong sơ đồ của bạn, bạn cần phải làmdoc.set('field', undefined)
evilcelery

3
xóa doc.field.foothì sao?
chovy

28
@evilcelery doc.set('field', undefined)có thể là không đủ vì chế độ nghiêm ngặt (mặc định) không cho phép đặt các trường không có trong lược đồ nữa. doc.set('field', undefined, { strict: false })hoạt động tốt.
Alexander Link

56

Bạn sẽ muốn làm điều này:

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

3
Điều đó sẽ chỉ đặt nó thành null - không phải những gì OP đang yêu cầu.
Ian Henry

25
Kể từ phiên bản 2.4.0, việc đặt khóa tài liệu thành không xác định sẽ chuyển $ unset tới mongodb aaronheckmann.posterous.com/mongoose-240
James Moore

30

Tôi sử dụng mongoose và sử dụng bất kỳ chức năng nào ở trên đã đáp ứng yêu cầu của tôi. Hàm biên dịch không có lỗi nhưng trường sẽ vẫn còn.

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

đã làm thủ thuật cho tôi.


Ủng hộ câu trả lời hữu ích này, quá tệ @ alexander-link đã không khiến nó trở thành câu trả lời vào năm 2015 ( stackoverflow.com/questions/4486926/… )
w00t

1
Cảm ơn bạn đã trả lời, đối với tôi, các giải pháp khác không hoạt động cho các đối tượng được lồng trong mảng!
BenSower

@BenSower Đây cũng là trường hợp của tôi. Chỉ giải pháp này làm việc tốt vì tôi đã phải xóa một lĩnh vực với mảng sau khi tìm thấy id một tài liệu cụ thể của
Luis Febro

Lưu ý rằng chuỗi là một đường dẫn đến khóa. Vì vậy, nếu đối tượng bạn muốn xóa được lồng vào nhau, bạn phải dẫn đến nó. Câu trả lời này đã giải quyết vấn đề của tôi!
Bradyo

8

Theo cú pháp mongo để xóa một số key bạn cần làm như sau:

{ $unset : { field : 1} }

Có vẻ ở Mongoose cũng vậy.

Biên tập

Kiểm tra ví dụ này .


Bạn có thể làm rõ câu trả lời này và đưa ra một ví dụ về mã liên quan đến mã ví dụ trên không?
Daniel Beardsley

xin lỗi nhưng tôi không rõ ràng tại mongoose. Cú pháp trên là cú pháp mongo, vì vậy tôi cho rằng trình điều khiển cho bất kỳ ngôn ngữ nào hỗ trợ điều này. Tôi đã tìm thấy một số ví dụ, hãy kiểm tra nó trong câu trả lời của tôi.
Andrew Orsich

1

Đây có thể là một vấn đề phụ như sử dụng

function (user)

thay vì

function(err, user)

cho cuộc gọi lại của tìm thấy? Tôi chỉ cố gắng giúp đỡ điều này vì tôi đã gặp trường hợp này.


1

Tài liệu Mongoose KHÔNG phải là một đối tượng javascript thuần túy và đó là lý do tại sao bạn không thể sử dụng toán tử xóa. (Hoặc unsettừ thư viện 'lodash').

Tùy chọn của bạn là đặt doc.path = null || undefined hoặc sử dụng phương thức Document.toObject () để chuyển doc mongoose thành đối tượng thuần túy và từ đó sử dụng nó như bình thường. Đọc thêm trong mongoose api-ref: http://mongoosejs.com/docs/api.html#document_Document-toObject

Ví dụ sẽ giống như sau:

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

1

Thử:

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

  delete user.key_to_delete;

  user.save();
});

0

vấn đề với tất cả các câu trả lời này là chúng hoạt động cho một lĩnh vực. ví dụ, giả sử tôi muốn xóa tất cả các trường khỏi Tài liệu của mình nếu chúng là một chuỗi trống "". Trước tiên, bạn nên kiểm tra xem trường có chuỗi trống không, hãy đặt nó vào $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

nếu bạn muốn xóa khóa khỏi bộ sưu tập, hãy thử phương pháp này. điều này làm việc cho tôi

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.