在 Mongoose 中跳过一层嵌套的子文档

Skip one nested level of subdocument in Mongoose

我有一个带有子文档的父架构。子文档有一个 属性 和一个嵌入对象数组:

子架构

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

父架构

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

Item.find returns 这样的对象上:

[
    {
        _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 的新手。

您需要在 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/) and a $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"
        }
}