我正在为建筑产品商店管理MongoDB数据库。最直接的系列是产品,对吧? 有很多产品,但是它们都属于5-8个类别中的一个,然后属于一小部分子类别中的一个子类。
例如:
-Electrical
*Wires
p1
p2
..
*Tools
p5
pn
..
*Sockets
p11
p23
..
-Plumber
*Pipes
..
*Tools
..
PVC
..
我将在网站客户端使用Angular来显示整个产品目录,我考虑使用AJAX来查询我想要的正确产品子集。
然后,我想知道我是否应该只管理一个集合:
{
MainCategory1: {
SubCategory1: {
{},{},{},{},{},{},{}
}
SubCategory2: {
{},{},{},{},{},{},{}
}
SubCategoryn: {
{},{},{},{},{},{},{}
}
},
MainCategory2: {
SubCategory1: {
{},{},{},{},{},{},{}
}
SubCategory2: {
{},{},{},{},{},{},{}
}
SubCategoryn: {
{},{},{},{},{},{},{}
}
},
MainCategoryn: {
SubCategory1: {
{},{},{},{},{},{},{}
}
SubCategory2: {
{},{},{},{},{},{},{}
}
SubCategoryn: {
{},{},{},{},{},{},{}
}
}
}
或每个类别的单个集合。文件数量可能不会高于500.但我关心的是:
我现在正在使用mongodb node.js module,而不是Mongoose。
插入产品,我还希望能够为每个新寄存器获取自动生成的ID(可能是顺序的)。但是,由于看起来很自然,我不会向用户提供 _id 。
查询子类别的整个文档集。也许最初只是获得一些属性。
查询特定文件(产品)的整个或特定属性子集。
修改产品的属性值。
答案 0 :(得分:5)
我同意客户端应该获得最简单的渲染结果。但是,将类别嵌入到产品中仍然是一个坏主意。权衡是一旦你想要改变,例如,一个类别的名称,它将是一场灾难。如果您考虑可能的用例,例如:
你会发现很难用你的数据结构做这些事情。
我目前的项目情况相同。所以这就是我的建议供您参考
首先,类别应该在一个单独的集合中。 DON' T 将类别嵌套到彼此中,因为它会使查找所有子类别的过程复杂化。查找所有子类别的传统方法是维护idPath
属性。例如,您的类别分为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"
}
使用idPath注意,不再需要parentId。让您更容易理解结构 一旦您需要查找类别100的所有子类别,只需执行查询:
db.collection("category").find({_id: /^0-100-/}, function(err, doc) {
// whatever you want to do
})
将类别存储在单独的集合中,在您的产品中,您需要通过_id引用它们,就像我们使用RDBMS时一样。例如:
{
... // other fields of product
categories: [100, 101, 102, ...]
}
现在,如果您想查找特定类别的所有产品:
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
}
})
幸运的是,类别集合通常非常小,内部(或数千)只有数百条记录。它并没有太大的变化。因此,您始终可以在内存中存储类别的实时副本,并且可以将其构造为嵌套对象,如:
[{
id: 100,
name: "level 1 category",
... // other fields
subcategories: [{
id: 101,
... // other fields
subcategories: [...]
}, {
id: 103,
... // other fields
subcategories: [...]
},
...]
}, {
// another top1 category
}, ...]
您可能希望每隔几个小时刷新一次此副本,所以:
setTimeout(3600000, function() {
// refresh your memory copy of categories.
});
我现在想到的就是这一切。希望它有所帮助。
修改强>
为每个用户提供int ID,$inc和findAndModify非常有用。你可能有一个idSeed集合:
{
_id: ...,
seedValue: 1,
forCollection: "user"
}
如果您想获得唯一ID:
db.collection("idSeed").findAndModify({forCollection: "user"}, {}, {$inc: {seedValue: 1}}, {}, function(err, doc) {
var newId = doc.seedValue;
});
findAndModify是mongodb提供的原子操作符。它将保证线程安全。并且查找和修改实际上发生在"事务"。
projection
参数文档。