MongoDB - 如何在数组中更新或插入对象

Posted

技术标签:

【中文标题】MongoDB - 如何在数组中更新或插入对象【英文标题】:MongoDB - How to Update or Insert object in array 【发布时间】:2021-07-21 10:10:22 【问题描述】:

我有以下收藏


        "likes": [],
        "_id": "6086f47a3e8c0411f0a66d22",
        "creator": "dimer",
        "picture": "",
        "title": "",
        "body": "hello world",
        "comments": [
            
                "isReady": true,
                "likes": [],
                "_id": "6086fcf33e8c0411f0a66d25",
                "creatorId": "607e50a16e852544d41a1d9d",
                "creator": "dimer",
                "body": "hello world",
                "replies": [],
                "timestamp": 1619459315854
            ,
        ],
        "createdAt": "2021-04-26T17:12:26.632Z",
        "updatedAt": "2021-04-27T04:22:28.159Z",
        "__v": 0
    ,

如果评论和帖子存在,我想向comment.replies 推送新回复。 如何在有条件的嵌套数组中更新或插入对象?

我试过了:

module.exports.createReply = async (req, res) => 
  const user_ID = req.body.creatorId;
  const post_ID = req.params.id;
  const comment_ID = req.body.commentId;

  if (!ID.isValid(user_ID) && !ID.isValid(post_ID) && !ID.isValid(comment_ID)) 
    return res.status(400).send("ID unknown");
  

  try 
    console.log("hello woorld");
    const reply = 
      creatorId: user_ID,
      creator: req.body.creator,
      body: req.body.body,
      timestamp: new Date().getTime(),
    ;
    console.log("reply", reply);
    await PostModel.findById(post_ID, (err, docs) => 
      console.log(comment_ID);
      const comment = docs.comments.find((comment) =>
        comment._id.equals(comment_ID)
      );
      console.log("comment", comment);
      if (!comment) return res.status(404).send("comment not found" + err);
      comment.replies = [...comment.replies, reply];

      return docs.save((err, docs) => 
        if (!err) return res.status(200).send(docs);
        return res.status(400).send(err);
      );
    );
   catch (error) 
    return res.status(400).send(err);
  
;

我认为我没有收到回复,因为我收到了这个错误:


    "errors": 
        "comments.4.creator": 
            "name": "ValidatorError",
            "message": "Path `creator` is required.",
            "properties": 
                "message": "Path `creator` is required.",
                "type": "required",
                "path": "creator"
            ,
            "kind": "required",
            "path": "creator"
        
    ,
    "_message": "post validation failed",
    "name": "ValidationError",
    "message": "post validation failed: comments.4.creator: Path `creator` is required."

这是我的模型:

const nongoose = require("mongoose");
const PostSchema = nongoose.Schema(
  
    creatorId: 
      type: String,
      // trim: true,
      // required: true,
    ,
    creator: 
      type: String,
      trim: true,
      required: true,
    ,
    title: 
      type: String,
      maxlength: 80,
    ,
    body: 
      type: String,
      trim: true,
      maxlength: 250,
      required: true,
    ,
    picture: 
      type: String,
    ,
    video: 
      type: String,
    ,
    likes: 
      type: [String],
      require: true,
    ,
    comments: 
      required: true,
      type: [
        
          isReady: 
            type: Boolean,
            default: true,
          ,
          creatorId: 
            type: String,
            required: true,
          ,
          creator: 
            type: String,
            required: true,
          ,
          timestamp: Number,

          body: 
            type: String,
            required: true,
            trim: true,
          ,
          likes: 
            type: [String],
            required: true,
          ,
          replies: 
            require: true,
            type: [
              
                isReady: 
                  type: Boolean,
                  default: true,
                ,
                creatorId: 
                  type: String,
                  required: true,
                ,
                creator: 
                  type: String,
                  required: true,
                ,
                body: 
                  type: String,
                  required: true,
                  trim: true,
                ,
                timestamp: Number,
              ,
            ],
          ,
        ,
      ],
    ,
  ,
  
    timestamps: true,
  
);

module.exports = nongoose.model("post", PostSchema);

【问题讨论】:

【参考方案1】:

就像错误所说,路径creator 是必需的。 确保回复包含“创建者”字段。

【讨论】:

我做了,但它说的是 cmets.4.creator,而不是 cmets.replies.4.creator 你有什么解决办法【参考方案2】:

要在更新的返回值中获取更新后的文档,需要使用 findOneAndUpdate 1 或 findAndModify 方法。这两种方法都有一个参数,您可以在其中指定返回更新后的文档。请注意,Mongoose ODM 有相应的方法,但语法可能略有不同。

我的解决方案:

module.exports.createReply = async (req, res) => 
  const user_ID = req.body.creatorId;
  const post_ID = req.params.id;
  const comment_ID = req.body.commentId;

  if (!ID.isValid(user_ID) && !ID.isValid(post_ID) && !ID.isValid(comment_ID)) 
    return res.status(400).send("ID unknown");
  

  try 
    const reply = 
      creatorId: user_ID,
      creator: req.body.creator,
      body: req.body.body,
      timestamp: new Date().getTime(),
    ;
    const query =  _id: post_ID ;
    const update =  $push:  "comments.$[elem].replies": reply  ;
    const options =  new: true, arrayFilters: [ "elem._id": comment_ID ] ;
    await PostModel.findOneAndUpdate(query, update, options);
    let updated = await PostModel.findOne( _id: post_ID );

    return res.status(200).send(
      data: updated.comments.find((comment) => comment._id.equals(comment_ID)),
    );
   catch (err) 
    return res.status(400).send( err: err );
  
;

【讨论】:

以上是关于MongoDB - 如何在数组中更新或插入对象的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB。如何更新数组内的json属性

如何使用 MongoDB 在数组中的对象中更新数组中的对象中的文档?

如何将一个对象插入到mongo数组中的另一个对象中

如何在 mongodb/mongoose 的嵌套数组中检查是不是存在并更新对象?

如何使用 mongoose 和 NodeJs 在 Mongodb 的数组字段中插入数据

如何更新数组NodeJS,MongoDB中的特定对象