[英]How should I model my MongoDB collection for nested documents?
I'm managing a MongoDB database for a building products store. 我正在管理建筑产品商店的MongoDB数据库。 The most immediate collection is products, right?
最直接的收藏是产品,对不对? There are quite several products, however they all belong to one among a set of 5-8 categories and then to one subcatefory among a small set of subcategories.
有很多产品,但是它们都属于一组5-8个类别中的一个,然后属于一小组子类别中的一个子类别。
For example: 例如:
-Electrical
*Wires
p1
p2
..
*Tools
p5
pn
..
*Sockets
p11
p23
..
-Plumber
*Pipes
..
*Tools
..
PVC
..
I will use Angular at web site client side to show whole products catalog, I think about AJAX for querying the right subset of products I want. 我将在网站客户端使用Angular来显示整个产品目录,我考虑使用AJAX查询所需的正确产品子集。
Then, I wonder whether I should manage one only collection like: 然后,我想知道是否应该管理一个唯一的集合,例如:
{
MainCategory1: {
SubCategory1: {
{},{},{},{},{},{},{}
}
SubCategory2: {
{},{},{},{},{},{},{}
}
SubCategoryn: {
{},{},{},{},{},{},{}
}
},
MainCategory2: {
SubCategory1: {
{},{},{},{},{},{},{}
}
SubCategory2: {
{},{},{},{},{},{},{}
}
SubCategoryn: {
{},{},{},{},{},{},{}
}
},
MainCategoryn: {
SubCategory1: {
{},{},{},{},{},{},{}
}
SubCategory2: {
{},{},{},{},{},{},{}
}
SubCategoryn: {
{},{},{},{},{},{},{}
}
}
}
Or a single collection per each category. 或每个类别一个集合。 The number of documents might not be higher than 500. However I care about a balance for:
文档数量可能不超过500。但是我关心以下方面的平衡:
I'm using mongodb node.js module , not Mongoose now. 我正在使用mongodb node.js模块 ,而不是Mongoose。
Inserts of products , I'd also like to have a way to obtain autogenerated ids (maybe sequential) per each new register. 产品插入 ,我还希望有一种方法来为每个新寄存器获取自动生成的ID(可能是顺序的)。 However, as it might seem natural I wouldn't offer the _id to the user.
但是,似乎很自然,我不会向用户提供_id 。
Querying the whole documents set of a subcategory. 查询子类别的整个文档集 。 Maybe just obtaining a few attributes at first.
也许一开始只是获得一些属性。
Querying whole or a specific subset of attributes of a document (product) in particular. 特别是查询 文档 (产品) 属性的全部或特定子集 。
Modifying a product's attributes values. 修改产品的属性值。
I agree client side should get the easiest result to render. 我同意客户端应获得最简单的渲染结果。 However, to nest categories into products is still a bad idea.
但是,将类别嵌套到产品中仍然不是一个好主意。 The trade off is once you want to change, for example, the name of a category, it will be a disaster.
权衡是一旦您想更改,例如类别的名称,那将是一场灾难。 And if you think about the possible usecases, for example:
如果您考虑可能的用例,例如:
You'll find it hard to do these stuff with your data structure. 您会发现很难用数据结构来完成这些工作。
I had same situation in my current project. 我在当前项目中也遇到了同样的情况。 So here's what I do for your reference.
因此,这是我的工作供您参考。
First, categories should be in a separate collection. 首先,类别应放在单独的集合中。 DON'T nest categories into each other, as it will complicate the procedure to find all subcategories.
不要将类别相互嵌套,因为这会使查找所有子类别的过程变得复杂。 The traditional way for finding all subcategories is to maintain an
idPath
property. 查找所有子类别的传统方法是维护
idPath
属性。 For example, your categories are divided into 3 levels: 例如,您的类别分为3个级别:
{
_id: 100,
name: "level1 category"
parentId: 0, // means it's the top category
idPath: "0-100"
}
{
_id: 101,
name: "level2 category"
parentId: 100,
idPath: "0-100-101"
}
{
_id: 102,
name: "level3 category"
parentId: 101,
idPath: "0-100-101-102"
}
Note with idPath, parentId is not necessary anymore. 请注意,对于idPath,不再需要parentId。 It's for you to understand the structure easier.
您可以更轻松地了解其结构。
Once you need to find all subcategories of category 100, simply do the query: 一旦您需要找到类别100的所有子类别,只需执行查询:
db.collection("category").find({_id: /^0-100-/}, function(err, doc) {
// whatever you want to do
})
With category stored in a separate collection, in your product you'll need to reference them by _id, just like when we use RDBMS. 由于类别存储在单独的集合中,因此在您的产品中,您需要使用_id来引用它们,就像使用RDBMS一样。 For example:
例如:
{
... // other fields of product
categories: [100, 101, 102, ...]
}
Now if you want to find all products in a certain category: 现在,如果要查找某个类别中的所有产品:
db.collection("category").find({_id: new RegExp("/^" + idPath + "-/"}, function(err, categories) {
var cateIds = _.pluck(categories, "_id"); // I'm using underscore to pluck category ids
db.collection("product").find({categories: { $in: cateIds }}, function(err, products) {
// products are here
}
})
Fortunately, category collection is usually very small, with only hundreds of records inside (or thousands). 幸运的是,类别集合通常很小,内部只有数百个记录(或数千个)。 And it doesn't varies a lot.
而且变化不大。 So you can always store a live copy of categories inside memory, and it can be constructed as nested objects like:
因此,您始终可以将类别的实时副本存储在内存中,并且可以将其构造为嵌套对象,例如:
[{
id: 100,
name: "level 1 category",
... // other fields
subcategories: [{
id: 101,
... // other fields
subcategories: [...]
}, {
id: 103,
... // other fields
subcategories: [...]
},
...]
}, {
// another top1 category
}, ...]
You may want to refresh this copy every several hours, so: 您可能需要每隔几个小时刷新一次此副本,因此:
setTimeout(3600000, function() {
// refresh your memory copy of categories.
});
That's all I get in mind right now. 这就是我现在要记住的一切。 Hope it helps.
希望能帮助到你。
EDIT: 编辑:
to provide int ID for each user, $inc and findAndModify is very useful. 为每个用户提供int ID, $ inc和findAndModify非常有用。 you may have a idSeed collection:
您可能有一个idSeed集合:
{ _id: ..., seedValue: 1, forCollection: "user" }
When you want to get an unique ID: 当您想要获得唯一的ID时:
db.collection("idSeed").findAndModify({forCollection: "user"}, {}, {$inc: {seedValue: 1}}, {}, function(err, doc) { var newId = doc.seedValue; });
The findAndModify is an atomic operator provided by mongodb. findAndModify是mongodb提供的原子运算符。 It will guarantee thread safety.
这将保证线程安全。 and the find and modify actually happens in a "transaction".
而查找和修改实际上发生在“交易”中。
projection
parameter. projection
参数文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.