Mongoose子文档与嵌套模式

时间:2013-03-04 18:43:01

标签: javascript node.js mongodb mongoose

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

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

var mainDoc = new Schema({
  names: [subDoc]
});

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});

我目前正在使用各个子网站,但我主要想知道性能或查询我可能会遇到的问题。

6 个答案:

答案 0 :(得分:57)

根据the docs,它完全相同。 但是,使用Schema也会添加_id字段(只要您没有禁用该字段),并且可能会使用更多资源来跟踪subdoc。

  

备用声明语法

     

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

答案 1 :(得分:33)

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

答案 2 :(得分:18)

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

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

http://askasya.com/post/largeembeddedarrays上的原帖。 您可以在https://stackoverflow.com/users/431012/asya-kamsky

上找到她的stackoverflow个人资料
  

首先,我们必须考虑为什么我们想要这样做   事情。通常情况下,我会建议人们嵌入他们的东西   总是希望在获取此文档时回来。翻转   这方面的一部分是你不想在文档中嵌入东西   你不想再回来了。

     

如果您将我执行的活动嵌入到文档中,那么它将非常适合   首先是因为我的所有活动都在那里并且只有一次阅读   你可以找回你想给我看的一切:"你最近   点击这里,这是你的最后两条评论"但是会发生什么   六个月过去了,我不在乎我做了很长时间的事情   除非我特意去,否则你不想向我展示它们   寻找一些旧的活动?

     

首先,您最终会返回越来越大的文档和关怀   关于它的越来越小的部分。但你可以使用投影   只返回一些数组,真正的痛苦就在于文档上   磁盘将变得更大,即使你只是,它仍将被读取   将部分返回给最终用户,但是因为我的活动是   只要我活跃,就不会停止,文件将继续   成长和成长。

     

最明显的问题是你最终会达到16MB   文件限制,但这根本不是你应该关心的   关于。不断增长的文件将越来越高   每次必须重新定位在磁盘上,即使你采取的成本   你的写作会减少碎片影响的步骤   整体上不必要地长,影响你的整体表现   整个申请。

     

还有一件事可以完全杀死你   应用程序的性能和索引这种不断增长的索引   阵列。这意味着文档每次都有   此数组被重定位,需要的索引条目数   updated更新与索引值的数量成正比   该文档,数组越大,该数字越大   是

     

我不希望这会吓到你使用数组时它们是好的   适合数据模型 - 它们是文档的强大功能   数据库数据模型,但与所有强大的工具一样,需要使用它   在适当的情况下,应小心使用。

答案 3 :(得分:12)

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

简单版本:

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

var mainDoc = new Schema({
  names: [nestedDoc]
});

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"
    ]
}

示例:

enter image description here

答案 4 :(得分:9)

我认为这可以通过SO上的多个帖子在其他地方处理。

只是几个:

关键在于,这里没有单一的答案,只有一系列相当复杂的权衡。

答案 5 :(得分:0)

两者之间有些区别:

  • 使用嵌套模式有助于验证。

  • 嵌套模式可以在其他模式中重复使用。

  • 嵌套模式将“ _id”字段添加到子文档中,除非您使用“ _id:false”