我如何为嵌套文档模拟我的MongoDB集合? [英] How should I model my MongoDB collection for nested documents?

查看:105
本文介绍了我如何为嵌套文档模拟我的MongoDB集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



例如:

  -Electrical 
*电线
p1
p2
..
*工具
p5
pn
..
*套接字
p11
p23
..
- 金额
*管道
..
*工具
..
PVC
..

我将使用Angular在网站客户端显示整个产品目录,我想到了AJAX查询我想要的正确的产品子集。



然后,我想知道我是否应该只管理一个集合:

  {

MainCategory1:{


SubCategory1:{
{},{},{},{},{},{},{}
}
SubCategory2:{
{},{},{},{},{},{},{}
}
子类别:{
{},{},{},{},{},{},{}
}
},
MainCategory2:{


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


SubCategory1:{
{},{},{},{},{} ,{},​​{}
}
SubCategory2:{
{},{},{},{},{},{},{}
}
子类别:{
{},{},{},{},{},{},{}
}
}
}

或每个类别单个集合。文件数量可能不会高于500.但是,我关心的是:




  • 快速DB答案,

  • 简单的服务器端DB查询,

  • 客户端用于将结果呈现为html的角色代码。



我正在使用 mongodb node.js模块,而不是Mongoose



我会做什么CRUD操作?




  • 产品插入,我也希望有一种方式来获得每个新注册的自动生成的ids(可能是顺序的)。但是,由于看起来很自然,我不会向用户提供 _id


  • 查询子类别的整个文件集。也许刚刚获得几个属性。


  • 查询整个或特定的文档属性子集



解决方案

我同意客户端应该获得最简单的结果。然而,将类别嵌套到产品中仍然是个坏主意。权衡一旦你想改变,例如,一个类别的名称,那将是一场灾难。如果您想到可能的用例,例如:




  • 列出所有类别

  • 查找全部

  • 查找某一类别的所有产品



您会发现我们很难在数据结构中做这些事情。



我在当前的项目中有相同的情况。所以这里是我为您的参考。

首先,类别应该在一个单独的集合。 不要将类别嵌套在一起,因为它将使查找所有子类别的过程复杂化。找到所有子类别的传统方式是维护一个 idPath 属性。例如,您的类别分为3个级别:

  {
_id:100,
name: level1 category
parentId:0,//表示它是顶级类别
idPath:0-100
}
{
_id:101,
name:level2 category
parentId:100,
idPath:0-100-101
}
{
_id:102,
名称:level3
parentId:101,
idPath:0-100-101-102
}

注意,对于idPath,parentId不再需要了。这是为了更容易理解结构。

一旦您需要查找类别100的所有子类别,只需执行以下查询:

  db.collection(category)find({_ id:/ ^ 0-100- /},function(err,doc){
//任何你想要做的
))

将类别存储在单独的集合中,在您的产品中,您需要引用它们通过_id,就像我们使用RDBMS时一样。例如:

  {
... //产品的其他字段
类别:[100, 101,102,...]
}

现在,如果你想查找所有产品在某个类别中:

  db.collection(category)find({_ id:new RegExp(/ ^ + idPath + -  /},函数(err,categories){
var cateIds = _.pluck(categories,_id); //我使用下划线来抽取类别ids
db 。收藏(product)find({categories:{$ in:cateIds}},function(err,products){
//产品在这里
}
})

幸运的是,类别收集通常很小,只有数百条记录(或数千),而且所以你可以随时在内存中存储类别的实时副本,并且可以被构造为嵌套对象,如:

  [{
id:100,
name:level 1 category,
... //其他字段
子类别:[{
id: 101,
... //其他字段
子类别:[...]
},{
id:103,
... //其他字段
子类别:[...]
},
...]
},{
//另一个top1类别
},... ]

您可能需要每几个小时刷新一次副本,所以:

  setTimeout(3600000,function(){
//刷新你的内存副本的类别。
});

这就是我现在想到的一切。希望它有帮助。



编辑:




    <

    为每个用户提供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提供的原子操作符。它将保证线程安全。发现和修改实际上发生在交易中。


  • 第二个问题已经在我的答案中。

  • 查询子集属性使用 mongodb手册进行描述。 NodeJS API几乎相同。阅读投影参数的文档。

  • $ set


I'm managing a MongoDB database for a building products store. 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.

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.

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:

  • quick DB answer,
  • easy server side DB querying, and
  • client-side Angular code for rendering results to html.

I'm using mongodb node.js module, not Mongoose now.

What CRUD operations will I do?

  • Inserts of products, I'd also like to have a way to obtain autogenerated ids (maybe sequential) per each new register. However, as it might seem natural I wouldn't offer the _id to the user.

  • 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:

  • list all categories
  • find all subcategories of a certain category
  • find all products in a certain category

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. For example, your categories are divided into 3 levels:

{
    _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. It's for you to understand the structure easier.
Once you need to find all subcategories of category 100, simply do the query:

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. 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. you may have a idSeed collection:

    {
        _id: ...,
        seedValue: 1,
        forCollection: "user"
    }
    

    When you want to get an unique 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. It will guarantee thread safety. and the find and modify actually happens in a "transaction".

  • 2nd question is in my answer already.
  • query subsets of properties is described with mongodb Manual. NodeJS API is almost the same. Read the document of projection parameter.
  • update subsets is also supported by $set of mongodb operator.

这篇关于我如何为嵌套文档模拟我的MongoDB集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆