ลบคีย์จากเอกสาร MongoDB โดยใช้ Mongoose


105

ฉันใช้Mongoose Library เพื่อเข้าถึง 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/…
Stephen

ฮ่า ๆ ไม่เป็นไรฉันเดาว่านี่เป็นโพสต์ของคุณ!
Stephen

คำตอบ:


172

ในเวอร์ชันแรกคุณจะต้องดรอปไดรเวอร์ 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)หรือถ้าคุณมีอินสแตนซ์เอกสารให้ตั้งค่าเส้นทางเป็นไม่ได้กำหนดแล้วบันทึก: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 })ทำงานได้ดี
Alexander Link

56

คุณจะต้องทำสิ่งนี้:

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

3
นั่นจะเป็นการตั้งค่าเป็นโมฆะ - ไม่ใช่สิ่งที่ OP ขอ
Ian Henry

25
ในเวอร์ชัน 2.4.0 การตั้งค่ารหัสเอกสารเป็นไม่ได้กำหนดจะส่งต่อ $ unset ไปยัง mongodb aaronheckmann.posterous.com/mongoose-240
James Moore

30

ฉันใช้พังพอนและการใช้ฟังก์ชันใด ๆ ข้างต้นทำให้ฉันมีความต้องการ ฟังก์ชันคอมไพล์ไม่มีข้อผิดพลาด แต่ฟิลด์จะยังคงอยู่

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

ทำเคล็ดลับให้ฉัน


การโหวตคำตอบที่มีประโยชน์นี้แย่เกินไป @ alexander-link ไม่ได้ให้คำตอบกลับมาในปี 2015 ( stackoverflow.com/questions/4486926/… )
w00t

1
ขอบคุณสำหรับคำตอบสำหรับฉันวิธีแก้ปัญหาอื่น ๆ ใช้ไม่ได้กับวัตถุที่ซ้อนอยู่ในอาร์เรย์!
BenSower

@ BenSower นี่ก็เป็นกรณีของฉันเหมือนกัน เฉพาะโซลูชันนี้ทำงานได้ดีเพราะฉันต้องลบฟิลด์ที่มีอาร์เรย์หลังจากค้นหารหัสของเอกสารเฉพาะ
Luis Febro

โปรดทราบว่าสตริงเป็นเส้นทางไปยังคีย์ ดังนั้นหากวัตถุที่คุณต้องการลบซ้อนกันคุณต้องพา ธ ไปที่วัตถุนั้น คำตอบนี้ช่วยแก้ปัญหาของฉันได้!
Bradyo

8

ที่ mongo syntax เพื่อลบคีย์คุณต้องทำดังต่อไปนี้:

{ $unset : { field : 1} }

ดูเหมือนพังพอนเหมือนกัน

แก้ไข

ตรวจสอบนี้ตัวอย่างเช่น


คุณช่วยอธิบายคำตอบนี้และยกตัวอย่างโค้ดที่เกี่ยวข้องกับโค้ดตัวอย่างด้านบนได้หรือไม่
Daniel Beardsley

ขอโทษ แต่ฉันไม่ได้ถูกมองเห็นที่พังพอน ด้านบนไวยากรณ์เป็นไวยากรณ์ mongo ดังนั้นฉันคิดว่าไดรเวอร์สำหรับภาษาใด ๆ รองรับสิ่งนี้ ฉันพบตัวอย่างตรวจสอบในคำตอบของฉัน
Andrew Orsich

1

นี่อาจเป็นปัญหาด้านข้างเช่นการใช้

function (user)

แทน

function(err, user)

สำหรับการโทรกลับของค้นหา? แค่พยายามช่วยในเรื่องนี้ตามที่ฉันมีอยู่แล้ว


1

เอกสารพังพอนไม่ใช่วัตถุจาวาสคริปต์ธรรมดาและนั่นเป็นเหตุผลที่คุณไม่สามารถใช้ตัวดำเนินการลบได้ (หรือ unsetจากไลบรารี 'lodash')

ตัวเลือกของคุณคือตั้งค่า doc.path = null || ไม่ได้กำหนดหรือใช้เมธอด Document.toObject () เพื่อเปลี่ยน mongoose doc เป็นวัตถุธรรมดาและจากที่นั่นใช้ตามปกติ อ่านเพิ่มเติมใน 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
});


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);

0

ฉันกำลังพยายามลบฟิลด์ที่เรียกว่า 'ปก' ออกจากเอกสารของฉัน แต่เป็นประเภทบัฟเฟอร์ ดังนั้นด้วยเหตุผลบางอย่างแม้ว่าฉันจะไม่ได้กำหนดมันก็ยังคงเป็นประเภทไบนารีในขณะที่ให้ผลลัพธ์ที่ไม่ได้กำหนด เส้นทางนี้จะส่งคืนฟิลด์ใบปะหน้าจากคุณสมบัติโปรไฟล์ที่ตรงกันของเอกสาร

`

exports.update = (req, res) => {
  let form = new formidable.IncomingForm();
  form.keepExtension = true;
  form.parse(req, (err, fields, files) => {
    if (err) {
      return res.status(400).json({
        error: "Photo could not be uploaded",
      });
    }
    let user = req.profile;
    user = _.extend(user, fields);

    if (fields.password && fields.password.length < 6) {
      return res.status(400).json({
        error: "Password should be min 6 characters long",
      });
    }
    if (fields.cover == null) {
      user.cover = undefined;
    }

    if (files.photo) {
      if (files.photo.size > 10000000) {
        return res.status(400).json({
          error: "Image should be less than 1mb",
        });
      }
      sharp(files.photo.path)
        .resize(300, 300, {
          fit: "cover",
        })
        .jpeg({
          quality: 90,
        })
        .toFile(`assets/users/${user.profile}.jpg`, (err, info) => {
          if (err) {
            return res.status(400).json({
              error: "unable to process the image",
            });
          }
        });
    }
    if (files.cover) {
      if (files.cover.size > 10000000) {
        return res.status(400).json({
          error: "Image should be less than 1mb",
        });
      }
      sharp(files.cover.path)
        .resize(1200, 675, {
          fit: "cover",
        })
        .jpeg({
          quality: 90,
        })
        .toBuffer((err, compressed, info) => {
          User.findOneAndUpdate(
            { profile: user.profile },
            { cover: compressed }
          )
            .select("_id")
            .exec((err, updatedUser) => {
              if (err)
                res.status(400).json({
                  error: "Unable to process the image",
                });
            });
        });
    }

    console.log("user", user);

    user.save((err, result) => {
      if (err) {
        return res.status(400).json({
          error: errorHandler(err),
        });
      }
      user.hashed_password = undefined;
      user.salt = undefined;
      user.photo = undefined;
      res.json(user);
      console.log("result", result);
    });
  });
};

`


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.