使用mongoose查询和更新深层嵌套的对象

时间:2018-05-31 17:30:18

标签: node.js mongodb mongoose

我有以下架构

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

我有办法实现这个目标吗?

1 个答案:

答案 0 :(得分:0)

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

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

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

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

您需要这样做,因为子文档与其父文档一起保存。检查mongoose doc 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 doc,here)进行过滤或排序。

关于模式中VersionKey (__v)的一点评论。默认情况下,此属性由Mongoose设置。因此你可以删除它们。查看关于it的Mongoose文档。