【问题标题】:Skip one nested level of subdocument in Mongoose在 Mongoose 中跳过一层嵌套的子文档
【发布时间】:2017-05-03 00:09:44
【问题描述】:

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

子架构

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

【问题讨论】:

    标签: node.js mongodb mongoose subdocument


    【解决方案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"
            }
    }
    

    【讨论】:

    • 干净简单。没有从 Mongoose API 中找到太多关于聚合的文档,这就是为什么我找不到解决方案,但现在正在阅读 MongoDB 文档。我应该如何管理数据库写入?更愿意对 GET 和 POST 使用相同的 JSON。
    • 大多数语言驱动程序将类似的设置复制到标准的 JavaScript shell 命令。您可以使用不同的 JSON 进行投影到您的写入,这完全没问题,当您回写数据库时,您应该考虑使用更新运算符,例如 $set$inc 等...
    猜你喜欢
    • 2020-05-02
    • 1970-01-01
    • 2015-07-03
    • 2018-09-04
    • 2016-04-25
    • 1970-01-01
    • 2020-03-14
    • 2021-03-26
    • 1970-01-01
    相关资源
    最近更新 更多