首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对嵌套文档的MongoDB集合进行建模?

如何对嵌套文档的MongoDB集合进行建模?
EN

Stack Overflow用户
提问于 2014-05-23 05:45:48
回答 1查看 2.4K关注 0票数 4

我正在管理一个建筑产品商店的MongoDB数据库。最直接的收集是产品,对吗?有相当多的产品,但它们都属于一组5-8类中的一个,然后在一个小的子类别中属于一个子类。

例如:

代码语言:javascript
复制
-Electrical
  *Wires
    p1
    p2
    ..
  *Tools
    p5
    pn
    ..
  *Sockets
    p11
    p23
    ..
-Plumber
  *Pipes
    ..
  *Tools
    ..
  PVC
    ..

我将使用在网站客户端的角度显示整个产品目录,我会考虑使用AJAX查询我想要的产品的正确子集。

然后,我想知道我是否应该管理一个只有这样的收藏:

代码语言:javascript
复制
{
    
    MainCategory1: {


        SubCategory1: {
        {},{},{},{},{},{},{}
        }
        SubCategory2: {
        {},{},{},{},{},{},{}
        }
        SubCategoryn: {
        {},{},{},{},{},{},{}
        }               
    },
    MainCategory2: {


        SubCategory1: {
        {},{},{},{},{},{},{}
        }
        SubCategory2: {
        {},{},{},{},{},{},{}
        }
        SubCategoryn: {
        {},{},{},{},{},{},{}
        }               
    },  
    MainCategoryn: {


        SubCategory1: {
        {},{},{},{},{},{},{}
        }
        SubCategory2: {
        {},{},{},{},{},{},{}
        }
        SubCategoryn: {
        {},{},{},{},{},{},{}
        }               
    }   
}

或者每个类别都有一个集合。文件数量可能不超过500份。然而,我关心的是平衡:

  • 快速回答,
  • 简单的服务器端DB查询,以及
  • 客户端角度代码,用于将结果呈现为html。

我用的是mongodb node.js模块,现在不是猫鼬。

我要做什么CRUD操作?

  • 插入产品,我也希望有一种方法来获得每个新寄存器的自动生成ids (可能是顺序的)。然而,似乎很自然,我不会向用户提供_id
  • 查询整个文档设置了一个子类别的。也许一开始只是获得一些属性。
  • 查询整体或文档(产品)属性的特定子集。
  • 修改产品的属性值。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-23 06:31:18

我同意客户端应该得到最容易渲染的结果。然而,将类别嵌套到产品中仍然是个坏主意。权衡是一旦你想要改变,例如,一个类别的名称,它将是一场灾难。如果您考虑到可能的使用情况,例如:

  • 列出所有类别
  • 查找某一类别的所有子类别
  • 查找某一类别中的所有产品

你会发现很难用你的数据结构来做这些事情。

我在目前的项目中也遇到过同样的情况。这就是我要做的,供你参考。

首先,类别应该在单独的集合中。不相互嵌套类别,因为查找所有子类别会使过程复杂化。查找所有子类别的传统方法是维护idPath属性。例如,将您的类别划分为三个级别:

代码语言:javascript
复制
{
    _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的所有子类别,只需执行以下查询:

代码语言:javascript
复制
db.collection("category").find({_id: /^0-100-/}, function(err, doc) {
    // whatever you want to do
})

将类别存储在单独的集合中,在您的产品中,您需要通过_id引用它们,就像使用关系数据库管理系统时一样。例如:

代码语言:javascript
复制
{
    ... // other fields of product
    categories: [100, 101, 102, ...]
}

现在,如果您想找到某个类别中的所有产品:

代码语言:javascript
复制
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
    }
})

幸运的是,类别集合通常非常小,里面只有数百条记录(或数千条)。而且变化不大。因此,始终可以在内存中存储类别的活动副本,并且可以将其构造为嵌套对象,如下所示:

代码语言:javascript
复制
[{
    id: 100,
    name: "level 1 category",
    ... // other fields
    subcategories: [{
        id: 101,
        ... // other fields
        subcategories: [...]
    }, {
        id: 103,
        ... // other fields
        subcategories: [...]
    },
    ...]
}, {
    // another top1 category
}, ...]

您可能需要每隔几个小时刷新一次此副本,因此:

代码语言:javascript
复制
setTimeout(3600000, function() {
    // refresh your memory copy of categories.
});

我现在只想到这些。希望能帮上忙。

编辑:

  • 要为每个用户提供int,$incfindAndModify非常有用。您可能有一个idSeed集合: { _id:.,seedValue: 1,forCollection:"user“} 当您想获得唯一的ID时: db.collection("idSeed").findAndModify({forCollection:"user"},{},{$inc:{seedValue: 1},{},函数(err,doc) { var newId = doc.seedValue; findAndModify是mongodb提供的原子操作符。这将保证线程的安全。而查找和修改实际上发生在“事务”中。
  • 第二个问题已经在我的回答中了。
  • 属性的查询子集用mongodb手册描述。NodeJS API几乎是一样的。读取projection参数的文档。
  • mongodb操作符的$set也支持update子集。
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23821786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档