Mongoose 删除数组中的子文档

Posted

技术标签:

【中文标题】Mongoose 删除数组中的子文档【英文标题】:Mongoose Delete SubDocument in Array 【发布时间】:2021-02-10 14:32:02 【问题描述】:

我正在使用 mongoose 为我的项目制作数据库,我的架构 Class 具有如下结构:

const mongoose = require('mongoose')

const classSchema = mongoose.Schema(
  _id: mongoose.Schema.Types.ObjectId,
  consultant: 
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Consultant',
    required: true
  ,
  startYear: 
    type: String,
    required: true
  ,
  classname: 
    type: String,
    required: true,
    unique: true
  ,
  studentList: [
    
      code: 
        type: String,
        required: true
      ,
      fullname: 
        type: String,
        required: true
      
    
  ]
)

const Class = mongoose.model('Class', classSchema)

module.exports = Class

如您所见,我有一个名为 studentList 的属性是一个数组,这就是它在 mongoose Atlas 中的存储方式

所以现在我想删除数组studentList 中的一个子文档,所以这是我的路线:

http://localhost:5000/users/:code

这就是我所做的:

    exports.delele_student_from_user = (req, res, next) => 
      var  code  = req.params;
      var  classname  = req.body;
    
      User.findOneAndDelete(
        classname,
        studentList: 
          $pull: 
            code,
          ,
        ,
      )
        .exec()
        .then((doc) => 
          console.log(`deleted user with code $code from colection User`);
          next();
        )
        .catch((err) => 
          console.log(err);
          return res.status(500).json( err );
        );
    ;

我得到了这个错误:

 MongoError: unknown operator: $pull
    at MessageStream.messageHandler (C:\Users\ASUS\OneDrive\Desktop\uet-backend\node_modules\mongoose\node_modules\mongodb\lib\cmap\connection.js:266:20)
    at MessageStream.emit (events.js:198:13)
    at processIncomingData (C:\Users\ASUS\OneDrive\Desktop\uet-backend\node_modules\mongoose\node_modules\mongodb\lib\cmap\message_stream.js:144:12)
    at MessageStream._write (C:\Users\ASUS\OneDrive\Desktop\uet-backend\node_modules\mongoose\node_modules\mongodb\lib\cmap\message_stream.js:42:5)
    at doWrite (_stream_writable.js:415:12)
    at writeOrBuffer (_stream_writable.js:399:5)
    at MessageStream.Writable.write (_stream_writable.js:299:11)
    at TLSSocket.ondata (_stream_readable.js:709:20)
    at TLSSocket.emit (events.js:198:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at TLSSocket.Readable.push (_stream_readable.js:224:10)
    at TLSWrap.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
  operationTime:
   Timestamp  _bsontype: 'Timestamp', low_: 3, high_: 1603874496 ,
  ok: 0,
  code: 2,
  codeName: 'BadValue',
  '$clusterTime':
    clusterTime:
      Timestamp  _bsontype: 'Timestamp', low_: 3, high_: 1603874496 ,
     signature:  hash: [Binary], keyId: [Long]  ,
  name: 'MongoError' 
DELETE /students/16022267 500 785.904 ms - 240

请告诉我如何解决这个问题,非常感谢,祝你有美好的一天

【问题讨论】:

我认为 pull 操作符与 findOneAndDelete 操作不兼容。我会尝试updateOne(因为类名是唯一的)否则拉操作可在数组本身的用户上使用。 studentList.pull(code) 其中 user 是 findeOne(classname) 的结果 【参考方案1】:

你需要使用update

exports.delele_student_from_user = async (req, res, next) => 
  var  code  = req.params;
  var  classname  = req.body;
  try 
    await User.update(
       classname ,
      
        $pull: 
          studentList:  code 
        
      
    );
    return res.status(200).json( message: "Student deleted" );
   catch (err) 
    return res.status(500).json( err );
  
;

我也使用了async / await,所以看起来更干净。

【讨论】:

【参考方案2】:

使用 findOneAndUpdate()\

您也可以直接在 MongoDB 中进行更新,而无需加载文档并使用代码对其进行修改。使用 $pull 或 $pullAll 运算符从数组中删除项目。

https://docs.mongodb.com/manual/reference/operator/update/pull/#up._S_pull

【讨论】:

以上是关于Mongoose 删除数组中的子文档的主要内容,如果未能解决你的问题,请参考以下文章

Node.js/mongoose - 数组中的子文档不会删除/移除

Mongoose 中的子文档数组

使用 Mongoose 更新数组中的子文档

将 select: false 设置为 mongoose 的子文档数组

将新对象插入到 mongoose 中的子文档数组字段中

将新对象插入到 mongoose 中的子文档数组字段中