Mongoose - 使用 findOneAndUpdate 更新子文档

Posted

技术标签:

【中文标题】Mongoose - 使用 findOneAndUpdate 更新子文档【英文标题】:Mongoose - Updating a subdocument using findOneAndUpdate 【发布时间】:2017-08-13 19:08:39 【问题描述】:

我不知道具体方法是否不起作用。 findOneAndUpdate 应该与子文档一起使用吗?

使用 react/redux/express.

路线:

  app.route("/api/positions/:position_id").put(function(req, res) 
const _id = req.params.position_id;
const update = req.body;
process.nextTick(function() 
  // for each element in req.body -> I will update the correct field
  Project.findOneAndUpdate(_id : _id, update,  new: true , function(
    err,
    updatedDoc
  ) 
    if (err)
      res.send(err);
    else if (!updatedDoc)
      res.json( message: "No Position Found", _id );
    else 
      console.log(updatedDoc);
      res.json(
        message: "Update Successful",
        updatedDoc
      ); 
  );
);

);

邮递员返回:


  "message": "No Position Found",
  "_id": "58d1908861f3513dc0c85f7d"

但是子文档肯定存在于数据库中:


    "_id": 
        "$oid": "58c32c197f37c62a944f0ad2"
    ,
    "name": "One",
    "phrase": "Two",
    "description": "Three",
    "userID": "58ac8e0ec1d5dc37043b8a7f",
    "open_positions": [
        
            "position_title": "Master Chief",
            "position_description": "Superman chief",
            "position_tags": [
                "Healthcare",
                "Finance",
                "Consumer Products"
            ]
        ,
        
            "position_title": "Master Chief",
            "position_description": "Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor Lorem Ipsum Dolor ",
            "position_tags": [
                "Healthcare",
                "Finance",
                "Consumer Products",
                "Healthcare",
                "Finance",
                "Consumer Products",
                "Healthcare",
                "Finance",
                "Consumer Products"
            ]
        ,
        
            "position_description": "please join us we are the best",
            "_id": 
                "$oid": "58d18fb8b1f3272de8b89158"
            ,
            "position_tags": [
                ""
            ]
        ,
        
            "position_description": "please join us we are the best",
            "_id": 
                "$oid": "58d18fc9d993233df4e52ace"
            ,
            "position_tags": [
                ""
            ]
        ,
        
            "position_description": "please join us we are the best",
            "_id": 
                "$oid": "58d18fdcd993233df4e52acf"
            ,
            "position_tags": [
                ""
            ]
        ,
        
            "position_title": "BEST POSITION",
            "position_description": "please join us we are the best",
            "_id": 
                "$oid": "58d18ffbd993233df4e52ad0"
            ,
            "position_tags": [
                ""
            ]
        ,
        
            "position_title": "BEST POSITION",
            "position_description": "please join us we are the best",
            "_id": 
                "$oid": "58d1908861f3513dc0c85f7d"
            ,
            "position_tags": [
                ""
            ]
        
    ],
    "fields": [
        "Healthcare",
        "Finance",
        "Consumer Products"
    ],
    "skills": [],
    "dateAdded": 
        "$date": "2017-03-10T22:43:37.544Z"
    ,
    "size": "2-5",
    "stage": "development",
    "visible": true,
    "__v": 5

我做错了什么?

编辑:

如果有帮助,这就是架构:

// schema for open positions in a project
var positionSchema = mongoose.Schema(
  position_title: String,
  position_description: String,
  position_tags: Array,
  archived: Boolean,
  archivedDate: Date
);

// schema for single project data
var projectSchema = mongoose.Schema(
  userID: String,
  name: String,
  phrase: String,
  visible: 
    type: Boolean,
    default: true
  ,
  positions: Boolean,
  stage: 
    type: String,
    default: "Idea"
  ,
  size: 
    type: String,
    default: "1"
  ,
  members: String,
  dateAdded: 
    type: Date,
    default: Date.now
  ,
  description: String,
  skills: Array,
  fields: 
    type: Array,
    default: ["Other"]
  ,
  open_positions: [positionSchema],
  archived: Boolean,
  archivedDate: Date
);

// expose schema to app
module.exports = mongoose.model("Project", projectSchema);

【问题讨论】:

你可以试试Project.findOneAndUpdate("open_positions._id" : _id, "open_positions.$" : update , new: true .... 吗? 真是废话。刚刚发生了什么?效果如何? 【参考方案1】:

您查询open_positions 嵌入数组中的_id 字段。所以在查询部分你必须引用open_positions,后跟它的id。

当您在查询部分使用数组引用时,您会得到占位符 $ 位置运算符,它引用了匹配数组元素的索引,并且在更新部分 Mongo 将 $ 替换为先前找到的数组索引,然后替换带有update 文档的数组元素。

使用

Project.findOneAndUpdate("open_positions._id" : _id,  "open_positions.$" : update ,  new: true .... 

【讨论】:

以上是关于Mongoose - 使用 findOneAndUpdate 更新子文档的主要内容,如果未能解决你的问题,请参考以下文章

在多个文件中使用 Mongoose Schema (mongoose)

使用 Mongoose / mongoose-dbref 使用和填充(真实的)DBRef 数组

NestJS 和 Mongoose 使用 Mongoose-Sequence

使用 mongoose.createConnection() 与 mongoose.connect() 时查询挂起

使用 mongoose.createConnection() 与 mongoose.connect() 时查询挂起

Egg中使用egg-mongoose和常用的Mongoose 方法