在MongoDB中构建数据的正确方法

时间:2016-05-09 13:00:55

标签: mongodb mongodb-query

我无法理解在mongodb中存储数据的正确方法。尝试阅读了很多链接,但未能得出可靠的结论。我习惯了RDBMS风格。我手头有一个关系数据,db是Mongo。对于这个问题 - 比方说,我有一本可以拥有约200万册书籍的藏书。还有一种称为订阅的东西(例如:溢价,标准等)。总计200万的每本书肯定至少是任何一个订阅的一部分(也可能是多个订阅的一部分)。我可以在系统中最多订阅200个订阅。

这是关注的重点。如何在此处构建我的馆藏。我尝试了以下

方法1 。创建名为subscription_book_association的集合,其中一个文档对应于订阅,并将此订阅的所有书ID存储为文档中的json。在这里,我面临的问题是,如果订阅的书籍数量超过0.4百万,我必须将所有这些书籍的ID存储在同一文档中,最终我的文档限制超过16MB。

方法2 。创建一个名为book_subscription_association的集合,其中一个文档对应于一本书,并且我将所有订阅ID存储在文档中的每本书(作为数组)中。在这种情况下,我看到每当我对我的数据执行任何写操作时(例如,为订阅分配/取消分配一些新书),我基本上必须使用$ push / $ pull运算符更新订阅数组。这似乎花了太长时间(比如3-4分钟)。

例如:

订阅

{
        "_id" : "Standard",
        "description" : "Standard Subscription",                
        "status" : "Active",        
}

{
        "_id" : "",
        "name" : "Java for beginners",
        "code" : "TECH",
        "vendor" : "XX Publications"
        "Author" : "AAA"
        "Year" : "2010"     
}

book_subscription_association

{
        "_id" : "",        
        "code" : "TECH",        
        "displayName" : "TECH/Java for beginners",
        "name" : "Java for beginners",
        "permission" : [
                "Standard:R",
                "Guest:R"
                "Premium:RW"                
        ],
        "roles" : [
                "Standard",
                "Premium",
                "Guest"
        ]
}

查询更新

db.book_subscription_association.update( { }, { $pull: { roles: "Guest" } }, false,true)
db.book_subscription_association.update( { }, { $push: { roles: "Guest" } }, false,true)

方法3 。创建一个名为book_subscription_mapping的集合(类似于RDBMS中的映射表),其中我针对每个适用的订阅单独存储每本书的关联。在这种情况下,我在这个集合中拥有的文档数量非常庞大。最糟糕的情况是我在这个集合中有(200万个X 200)文档。这会占用大量存储空间,更新/读取查询也不是很有效。

2 个答案:

答案 0 :(得分:0)

您采取的方法应该基于您期望更频繁的查询类型。

例如,如果您希望有更多查询询问订阅中的可用图书,您应该在订阅文档中包含一个列表,其中包含您希望向用户显示的详细信息(ID,标题等)。

另一方面,如果您希望有更多查询询问哪些订阅包含某本图书,那么您应该在该图书文档中包含订阅所需的所有详细信息。

实际上,在您的情况下,方法1或方法2之间的选择严格基于您对查询的期望。

关于您对方法1的存储ID的关注,您可以使用反向方法,以防订阅的图书集非常大(仅在该特定订阅中未包含的图书的ID中存储)。根据您期望的订阅范围,这可能实际上作为一般模式有效。

如果这种反向方法不起作用(每个订阅中仍有太多书籍),那么您最好的做法是遵循方法2并索引包含订阅列表的数组。您在帖子中显示的更新命令会影响整个集合(2 mil项目),因此它们需要更长的时间是很自然的。

有关如何对表进行非规范化的更多信息,MongoDB有一个nice series of blog posts on the topic

答案 1 :(得分:0)

在对收集文档进行建模时,首先应该记住非规范化。您可以同时保留"预订数据&订阅数据"在单个集合中,始终建议将查询或查询序列的所有相关数据保留在同一磁盘位置(相同集合)中,以获得更好的性能。

请参阅以下链接以了解有效的模型设计。

参考:Updating large number of records in a collection