简体   繁体   English

我应该如何为嵌套文档建模MongoDB集合?

[英]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。但是我关心以下方面的平衡:

  • quick DB answer, 快速的数据库答案,
  • easy server side DB querying, and 轻松的服务器端数据库查询,以及
  • client-side Angular code for rendering results to html. 用于将结果呈现为html的客户端Angular代码。

I'm using mongodb node.js module , not Mongoose now. 我正在使用mongodb node.js模块 ,而不是Mongoose。

What CRUD operations will I do? 我将执行哪些CRUD操作?

  • 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: 如果您考虑可能的用例,例如:

  • 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. 查找所有子类别的传统方法是维护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, $ incfindAndModify非常有用。 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". 而查找和修改实际上发生在“交易”中。

  • 2nd question is in my answer already. 第二个问题已经在我的答案中。
  • query subsets of properties is described with mongodb Manual . 查询的属性子集在mongodb Manual中进行了描述。 NodeJS API is almost the same. NodeJS API几乎相同。 Read the document of projection parameter. 阅读projection参数文件。
  • update subsets is also supported by $set of mongodb operator. mongodb运算符的$ set也支持更新子集。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将 MongoDB-atlas 集合中的特定文档与存储在同一集群中不同集合中的文档相关联? - How do I associate specific documents in a collection in MongoDB-atlas to documents that are stored in a different collection in the same cluster? MongoDB的。 我应该为我的项目选择哪种数据模型? - MongoDB. Which data model I should choose for my project? mongoDB 更新采集文件 - mongoDB update collection documents Mongoose和MongoDB-似乎无法在我的收藏夹中找到文档 - Mongoose and MongoDB - Can't seem to find documents in my collection 我如何打印带有承诺的mongoDB集合中的100多个文档 - How can I print more than 100 documents from mongoDB collection with promises 如何使用 ejs 从 mongoDB 集合中提取文档,以便每个文档在浏览器上出现一次? - How do I extract documents from a mongoDB collection using ejs such that each appears once on browser? 如何使用 Node.js 返回 MongoDB 集合中的文档数? - How can I return the number of documents in a MongoDB collection using Node.js? 如何将嵌套在一个集合中的所有值与另一个集合(mongodb)中的值进行匹配? - How can I match all values nested in a collection to values in another collection (mongodb)? 如何总结 mongodb 集合中的值? - How can I sum up values in my mongodb collection? MongoDB 我应该制作另一个系列还是应该嵌入它 - MongoDB should i make another collection or should i embed it
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM