【问题标题】:Querying and updating a deeply nested object with mongoose使用 mongoose 查询和更新深度嵌套的对象
【发布时间】:2018-11-10 18:57:40
【问题描述】:

我有以下架构

const ButtonSchema = new mongoose.Schema({
    conditions: mongoose.Schema.Types.Mixed
})

// Data Model
const DataSchema = new mongoose.Schema({
    buttons: [ButtonSchema],
    __v: {type: Number, default: 0}
})

//Question Model
const QuestionSchema = new mongoose.Schema({
    data: [DataSchema],
    __v: {type: Number, default: 0}
})

// Dialog Model
const Dialog = mongoose.model('Dialog', new mongoose.Schema({
    name: String,
    questions: [QuestionSchema]
}))

所以本质上,对象是这样的

{
    "download_data": [
        {
            "__v": 0,
            "data": [
                {
                    "text": [
                        "xxxx"
                    ],
                    "__v": 0,
                    "buttons": [],
                    "_id": "5afdf6cf1c1cc542c4580511",
                    "conditions": {
                        "false": {
                            "type": "endDialog",
                            "data": [
                                {
                                    "text": []
                                }
                            ]
                        }
                    }
                }
            ],
            "_id": "5afdf6cf1c1cc542c4580510",
            "type": "confirm"
        },
        {
            "__v": 0,
            "data": [
                {
                    "text": [
                        "xxxx"
                    ],
                    "__v": 0,
                    "buttons": [],
                    "_id": "5afdf6cf1c1cc542c458050f"
                }
            ],
            "_id": "5afdf6cf1c1cc542c458050e",
            "type": "endDialog"
        }
    ]}

如您所见,我有唯一的问题对象的 ID 和数据对象的 ID

在更新期间,我希望只通过 _id 更新特定的数据字段

我可以通过这个检索一个特定的问题

return DialogSchema.findOne({'questions._id': req.params.subId})
    .then(function(data){
         // this doesnt work
        return data.questions[req.params.index].update(req.body)
    })
    .then(function(data){
        console.log('data :', data)
    })
    .catch(function(err){
        console.log('err: ', err)
    })

但理想情况下,我只想检索 DataSchema 对象(作为数组对象插入 QuestionsSchema 对象中)

但这不起作用

  return DialogSchema.findOne({'questions.data._id': req.params.subId})
        .then(function(data){
            console.log('data : ', data)
        })
        .catch(function(err){
            console.log('err: ', err)
        })

有什么办法可以做到吗?

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    因为QuestionSchema 中的data 字段是一个数组,所以您不能只访问子文档的嵌套属性。您检索问题的第一个查询,然后必须稍微更新数据。首先,查询数据的不是 Schema,而是您的 Model 实例。而且因为req.params.subIdQuestion Id,所以在该模型上进行查询会更有效:

    return Question.findOne({'_id': req.params.subId})
    .then(function(question) {
        ...
    })
    

    但要更新特定问题的数据,您需要更新 Question 模型,而不是 Data 模型:

    ...
    .then(function(question) {
       questions.data[req.params.index] = req.body
       return question.save()
    }
    

    您需要这样做,因为子文档与其父文档一起保存。查看 mongoose 文档,here

    注意questions.data 应该返回一个ObjectId 的数组,而不是一个Data 文档的数组。要解决这个问题,您可以使用populate() 方法,如下所示:

    return Question.findOne({'_id': req.params.subId})
    .populate('data')
    .then(function(question) {
        // Here questions.data is an Array of sub-documents
        ...
    })
    

    如有必要,您可以过滤或排序填充的 data 数组(Mongoose 文档,here)。

    只是对您架构中的VersionKey (__v) 的一个小评论。此属性默认由 Mongoose 设置。因此,您可以删除它们。查看有关 it 的 Mongoose 文档。

    【讨论】:

      猜你喜欢
      • 2023-03-25
      • 2018-06-04
      • 1970-01-01
      • 2013-06-03
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      相关资源
      最近更新 更多