繁体   English   中英

Mongoose 子文档与嵌套模式

[英]Mongoose subdocuments vs nested schema

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

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

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

要么

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

我目前在任何地方都使用 subdocs,但我主要想知道我可能遇到的性能或查询问题。

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

替代声明语法

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

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

如果是静态文档或由于性能影响不超过几百个,则应使用嵌入式文档。 我已经讨论过这个问题一段时间了。 最近,作为 MongoDB 解决方案架构师的 Asya Kamsky 写了一篇关于“使用子文档”的文章。

我希望这对正在寻找解决方案或最佳实践的人有所帮助。

http://askasya.com/post/largeembeddedarrays上的原始帖子。 您可以在https://stackoverflow.com/users/431012/asya-kamsky上访问她的 stackoverflow 个人资料

首先,我们必须考虑为什么我们要做这样的事情。 通常,我会建议人们嵌入他们在获取此文档时总是想取回的内容。 这样做的另一面是您不想在文档中嵌入不想拿回来的东西。

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

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

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

您还可以做一件事,它会完全降低应用程序的性能,那就是索引这个不断增加的数组。 这意味着每次重定位具有此数组的文档时,需要更新的索引条目的数量与该文档中索引值的数量成正比,数组越大,该数量将越大是。

当数组非常适合数据模型时,我不希望这让您害怕使用数组 - 它们是文档数据库数据模型的强大功能,但与所有强大的工具一样,它需要在正确的情况下使用并且应该小心使用。

基本上,创建一个变量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"
    ]
}

例子:

在此处输入图片说明

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

一些:

关键是这里没有单一的答案,只有一组相当复杂的权衡。

两者之间有一些区别:

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

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

  • 除非您使用了“_id:false”,否则嵌套架构将“_id”字段添加到子文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM