Mongoose子文档与嵌套模式

cyb*_*bat 111 javascript mongoose mongodb node.js

我很好奇在我的主模式中使用子文档与更深层的优缺点:

var subDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [subDoc]
});
Run Code Online (Sandbox Code Playgroud)

要么

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});
Run Code Online (Sandbox Code Playgroud)

我现在到处都在使用subdocs,但我主要想知道性能或查询我可能会遇到的问题.

And*_*dyL 61

根据文档,它完全相同.但是,使用Schema也会添加一个_id字段(只要你没有禁用它),并且可能会使用更多资源来跟踪subdocs.

备用声明语法

v3中的新功能如果您不需要访问子文档模式实例,您也可以通过简单地传递对象文字来声明子文档[...]

  • 这就是子文档的工作方式.它们嵌入在文档中.在玩mongoose之前,请确保您了解底层的MongoDB. (17认同)

son*_*one 36

如果您有在模型的各个部分中重复使用的模式,那么为子文档定义单独的模式可能很有用,因此您不必自己复制.

  • 这是一个很好的答案.有时我在多个模型中使用子文档,或者我在模型中有两个需要区分的字段,但仍然具有相同的子文档结构. (4认同)
  • 您还应该考虑保存冗余信息的优点/缺点。 (2认同)

efk*_*kan 21

如果是静态文档,则应使用嵌入式文档,或者由于性能影响,应使用不超过几百个的嵌入式文档.我刚才谈到了这个问题.最近,作为MongoDB解决方案架构师的Asya Kamsky撰写了一篇关于"使用子文档"的文章.

我希望这有助于谁在寻找解决方案或最佳实践.

http://askasya.com/post/largeembeddedarrays上的原帖.您可以访问/sf/users/30170871/上的 stackoverflow配置文件

首先,我们必须考虑为什么我们想做这样的事情.通常情况下,我会建议人们在获取此文档时嵌入他们总想要回复的内容.另一方面,您不希望在文档中嵌入您不想再使用它的东西.

如果你将我执行的活动嵌入到文档中,它首先会很好用,因为我的所有活动都在那里,只需一次阅读就可以找回你想要给我看的所有内容:"你最近点击了这里和这里这是你的最后两条评论"但是经过六个月后会发生什么,我不关心我很久以前做过的事情,除非我特意去寻找一些旧的活动,否则你不想向我展示它们?

首先,您最终会返回越来越大的文档,并关注它的越来越小的部分.但是你可以使用projection只返回一些数组,真正的痛苦是磁盘上的文件会变大,即使你只是将部分内容返回给最终用户,它仍然会被读取,但是因为只要我活跃,我的活动就不会停止,因此该文件将继续增长和发展.

最明显的问题是最终你会达到16MB的文件限制,但这根本不是你应该关注的.每次必须重新定位到磁盘上时,不断增长的文档会产生越来越高的成本,即使您采取措施来减轻碎片的影响,您的写入总体上也会不必要地长,从而影响整个应用程序的整体性能.

还有一件事你可以完全扼杀你的应用程序的性能,那就是索引这个不断增加的数组.这意味着每次重新定位具有此数组的文档时,需要更新的索引条目数与该文档中索引值的数量成正比,并且数组越大,该数字越大是.

当它们非常适合数据模型时,我不希望这会吓到你使用数组 - 它们是文档数据库数据模型的强大功能,但是像所有强大的工具一样,它需要在适当的环境中使用它应该小心使用.

  • 这应该是最佳答案。这真是钱。MongoDB自己的白皮书说的差不多。 (2认同)

Way*_*hiu 13

基本上,创建一个变量nestedDov并将其放在这里name: [nestedDov]

简单版本:

var nestedDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [nestedDoc]
});
Run Code Online (Sandbox Code Playgroud)

JSON示例

{
    "_id" : ObjectId("57c88bf5818e70007dc72e85"),
    "name" : "Corinthia Hotel Budapest",
    "stars" : 5,
    "description" : "The 5-star Corinthia Hotel Budapest on the Grand Boulevard offers free access to its Royal Spa",
    "photos" : [
        "/photos/hotel/corinthiahotelbudapest/1.jpg",
        "/photos/hotel/corinthiahotelbudapest/2.jpg"
    ],
    "currency" : "HUF",
    "rooms" : [
        {
            "type" : "Superior Double or Twin Room",
            "number" : 20,
            "description" : "These are some great rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/2.jpg",
                "/photos/room/corinthiahotelbudapest/5.jpg"
            ],
            "price" : 73000
        },
        {
            "type" : "Deluxe Double Room",
            "number" : 50,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 92000
        },
        {
            "type" : "Executive Double Room",
            "number" : 25,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 112000
        }
    ],
    "reviews" : [
        {
            "name" : "Tamas",
            "id" : "/user/tamas.json",
            "review" : "Great hotel",
            "rating" : 4
        }
    ],
    "services" : [
        "Room service",
        "Airport shuttle (surcharge)",
        "24-hour front desk",
        "Currency exchange",
        "Tour desk"
    ]
}
Run Code Online (Sandbox Code Playgroud)

例:

在此输入图像描述

  • 也许对OP不起作用,但我发现这非常有用.谢谢. (15认同)
  • 这根本没有解决性能问题之一。 (2认同)
  • 问题不是询问如何进行嵌套模式.它讨论了Mongoose是否更适合嵌套模式或嵌入式子文档.基本上我们正在谈论Mongoose更喜欢彼此的基准或排序或边缘情况.正如所选答案所提到的那样,它似乎没有任何区别,至少从V3开始. (2认同)

Gat*_* VP 9

我认为这是由SO上的多个帖子在其他地方处理的.

一些:

最重要的是,这里没有单一的答案,只有一套相当复杂的权衡.

  • 也许我没有正确地表达我的问题 - 这不是我应该如何构建我的数据库的问题,而是使用子模式与仅在更深层中编写数组的内部结构.我使用子模式的主要原因是我可以使用自定义模式类型并让它们验证 - 这对嵌套数组不起作用(来自我在SO上的上一个问题).尽管我可以告诉一个suboc与嵌套数组几乎相同 - 我只是不知道它的内部 - 如果使用它们会产生性能问题等. (3认同)