【问题标题】:Why is Mongoose repeating the top-level properties in a document sub-structure?为什么 Mongoose 在文档子结构中重复顶级属性?
【发布时间】:2018-07-12 14:33:06
【问题描述】:

我有一个从具有子结构的模式定义的 Mongoose“用户”模型,以表示用户的选项/首选项。

当我实例化模型并在节点调试器中检查它时,它具有在子结构的每个级别重复的顶级用户属性,如姓名、电子邮件、create_date 等。

事实上,它似乎具有上一层的所有属性,添加到子结构的每一层。例如“选项”在“助手”和“默认”下重复。

该程序运行良好,因为每个级别的定义属性都在那里,但是它周围有很多垃圾,这让我担心我设置错了,它使用了过多的内存,奇怪地递归并可能导致奇怪问题。

例如稍微简化的版本:

'use strict';
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
    name: String,                   // full name
    create_date: Date,              // signup date
    email: String,                  // email == username
    password: String,               // hashed password
    options: {
        assistants: {
            default: {
                enabled: Boolean,   // Turn assistant on
            },
        },
    .... (other settings)
    },
});

module.exports = mongoose.model('User', UserSchema);

稍后我通过 ID 获取用户:

const userModel = require(modelDir+'/user');

userModel.findById(userId (err, user)=>{
    // adjust user.options from GUI input, then re-save
    user.save((err)=>{
        ... etc
    }
}

在节点调试器中,从数据库中获取的用户显示如下:

user:model
    $__: internalCache{...}
    $init: true
    create_date: (...)
    email: (...)
    errors: undefined
    id: (...)
    isNew: false
    name: (...)
    options: model
        $init: true
        assistants: model
            $init: true
            create_date: undefined
            default: model
                $init: true
                assistants: undefined
                create_date: undefined
                email: undefined
                enabled: false          <= the only real property!
                id: undefined
                name: undefined
                options: undefined
... etc
            email: undefined
            id: undefined
            name: undefined
            options: undefined
            password: undefined
...etc
        $__: internalCache{...}
        $__isNested: true
        email: undefined        <= these ones are greyed-out
        id: undefined
        name: undefined
        options: undefined
        password: undefined

如果我从 mongo shell 中获取它,它看起来和我预期的一样,所以它与它的保存方式无关。

{
    "_id": ObjectId("5a6bdbf29c297d0eccb702ec"),
    "name": "Mr Test",
    "email": "...",
    "password": "...",
    "options": {
        "assistants": {
            "default": {
                "enabled": true
            }
        },
    // other stuff removed...
    },
    "__v": 1
}

我是否为使用子结构而错误地创建了 Mongoose 架构?

"mongoose": {
  "version": "4.11.12",

$ mongod --version
db version v3.6.2

$ node -v
v9.4.0

【问题讨论】:

  • 如何获取用户? (代码行)您在此处发布的user:model 似乎是 Model 而不是特定结果。
  • 我已经更新了问题 - 它是通过 findById。

标签: node.js mongodb mongoose mongoose-schema


【解决方案1】:

默认情况下 mongoose 使用MongooseDocuments 包装结果。这为您提供了额外的功能,例如您正在使用的 save() 函数。因此,您看到的额外属性并非来自您的 MongoDB 服务器。

我是否为使用子结构而错误地创建了 Mongoose 架构?

来自官方Mongoose schema guide,看来你的做法是对的。

也可以为键分配包含更多键/类型定义的嵌套对象。

如果你想要另一种方式来定义你的架构,有Subdocuments

子文档是嵌入在其他文档中的文档。在 Mongoose 中,这意味着您可以将模式嵌套在其他模式中。


要从 mongo 获取原始结果,您可以在查询中使用 lean() 方法。不幸的是,这意味着您将没有save() 功能,需要以不同的方式“重新保存”。这是便利性和性能之间的权衡。

精益运营商很好地解释了in this blog post

这是来自文档:Query.protoype.lean()(或Query.lean() in mongoose v4.x

启用了精简选项的查询返回的文档是纯 JavaScript 对象,而不是 MongooseDocuments。他们没有应用保存方法、getter/setter 或其他 Mongoose 魔法。

...

这是高性能只读场景的绝佳选择,尤其是与流结合使用时。

【讨论】:

  • 这不能解释为什么架构属性在每个级别都重复?
  • 正如您对 shell 的测试所表明的那样,它不是来自 Mongo。您看到的其他属性是 MongooseDocument 包装器的一部分,以及 mongoose 在内部的工作方式。我无法确定为什么它会重复,因为这需要深入了解mongoose 代码,而我还没有这样做。也就是说,我不知道带有文档嵌套的模式存在问题。 MongoDB 是一个文档数据库,确实支持嵌套文档。猫鼬也是:mongoosejs.com/docs/subdocs.html
猜你喜欢
  • 2015-08-08
  • 2021-03-09
  • 2019-05-27
  • 2018-05-02
  • 2015-11-08
  • 2018-05-23
  • 2016-01-09
  • 2016-02-29
  • 2019-04-03
相关资源
最近更新 更多