在Mongoose中跳过一个嵌套级别的子文档

时间:2016-12-17 09:32:38

标签: node.js mongodb mongoose subdocument

我有一个带有子文档的父模式。子文档具有一个包含嵌入对象数组的属性:

子架构

var snippetSchema = new Schema({
    snippet: [
        {
            language: String,
            text: String,
            _id: false
        }
    ]
});

父架构

var itemSchema = new Schema({
    lsin: Number,
    identifier: {
        isbn13: Number,
    },
    title: snippetSchema,
});

Item.find上返回一个像这样的对象:

[
    {
        _id: (...),
        lsin: 676765,
        identifier: {
            isbn13: 8797734598763
        },
        title: {
            _id: (...),
            snippet: [
                {
                    language: 'se',
                    text: 'Pippi Långstrump'
                }
            ]
        }
    }
]

当对象返回给客户端时,我想跳过子文档的一个嵌套级别:

[
    {
        _id: (...),
        lsin: 676765,
        identifier: {
            isbn13: 8797734598763
        },
        title: {
            language: 'se',
            text: 'Pippi Långstrump'
        }
    }
]

到目前为止,我已经尝试过:

#1使用getter

function getter() {
    return this.title.snippet[0];
}

var itemSchema = new Schema({
    ...
    title: { type: snippetSchema, get: getter } 
});

但它会创建一个无限循环,从而产生RangeError: Maximum call stack size exceeded

#2使用虚拟属性

var itemSchema = new Schema({
    ..., {
    toObject: {
        virtuals: true
    }
});

itemSchema
    .virtual('title2')
    .get(function () {
        return this.title.snippet[0];
});

这将生成所需的嵌套级别,但是在新属性下,这是不可接受的。据我所知,没有办法用虚拟属性覆盖属性。

问题是:还有其他方法可以获得所需的输出吗?整个应用程序中将有几个对snippetSchema的引用,并且首选DRY方法。

我是MongoDB和Mongoose的新手。

1 个答案:

答案 0 :(得分:1)

您需要在mongodb聚合管道中使用$project

在我的数据库中,我有以下内容:

> db.items.find().pretty()
{
        "_id" : 123,
        "lsin" : 676765,
        "identifier" : {
                "isbn13" : 8797734598763
        },
        "title" : {
                "_id" : 456,
                "snippet" : [
                        {
                                "language" : "se",
                                "text" : "Pippi Långstrump"
                        }
                ]
        }
}

然后我们只需要创建一个简单的聚合查询:

db.items.aggregate([
    {$project: { lsin: 1, identifier: 1, title: { $arrayElemAt: [ '$title.snippet', 0 ] }}}
])

这只是使用$ project(https://docs.mongodb.com/v3.2/reference/operator/aggregation/project/)和$ arrayElemAt(https://docs.mongodb.com/v3.2/reference/operator/aggregation/arrayElemAt/)来投射数组中的第一个项目。如果我们执行该操作,我们将获得以下内容:

{
        "_id" : 123,
        "lsin" : 676765,
        "identifier" : {
                "isbn13" : 8797734598763
        },
        "title" : {
                "language" : "se",
                "text" : "Pippi Långstrump"
        }
}