【问题标题】:designing a schema in mongodb在 mongodb 中设计模式
【发布时间】:2016-07-19 19:32:02
【问题描述】:

假设我有两个架构:类别和产品。现在我需要第三个模式,称为列表。管理员可以创建一个包含多个类别的列表,而这些类别又将包含多个产品。

一个类别也可以在多个列表中,一个产品可以在任意数量的类别中。我总是使用以下方式创建架构。

lists: {
   _id: '1',
   name: 'list 1',
   categories: [{
       categoryId: '201',
       products: [
           {
              productId: '301',
              name: 'product 1'
           },
           {
              productId: '302',
              name: 'product 2'
           }
       ]
   },
   {
       categoryId: '202',
       products: [
           {
              productId: '302',
              name: 'product 2'
           },
           {
              productId: '304',
              name: 'product 4'
           }
       ]           
   }]
}

这样的问题是,如果我必须从类别中删除产品,我必须遍历所有产品并找到产品并将其删除。当我只需要查询一个产品或一个类别时,我必须这样做。有没有更好的方法来创建列表架构?

【问题讨论】:

  • Scheme 标签用于 lisp 语言。

标签: mongodb


【解决方案1】:

如果您执行aggregateunwind 您的数组,则不必循环遍历结果。看看那个查询:

db.device.aggregate([{
    "$unwind": "$categories"
},{
    "$unwind": "$categories.products"
}])

会将您的数组转换为 json 对象:

{ "_id" : "1", "name" : "list 1", "categories" : { "categoryId" : "201", "products" : { "productId" : "301", "name" : "product 1" } } }
{ "_id" : "1", "name" : "list 1", "categories" : { "categoryId" : "201", "products" : { "productId" : "302", "name" : "product 2" } } }
{ "_id" : "1", "name" : "list 1", "categories" : { "categoryId" : "202", "products" : { "productId" : "302", "name" : "product 2" } } }
{ "_id" : "1", "name" : "list 1", "categories" : { "categoryId" : "202", "products" : { "productId" : "304", "name" : "product 4" } } }
{ "_id" : "2", "name" : "list 2", "categories" : { "categoryId" : "201", "products" : { "productId" : "303", "name" : "product 3" } } }
{ "_id" : "2", "name" : "list 2", "categories" : { "categoryId" : "201", "products" : { "productId" : "304", "name" : "product 4" } } }
{ "_id" : "2", "name" : "list 2", "categories" : { "categoryId" : "202", "products" : { "productId" : "302", "name" : "product 2" } } }
{ "_id" : "2", "name" : "list 2", "categories" : { "categoryId" : "202", "products" : { "productId" : "304", "name" : "product 4" } } }

根据自己的喜好组合一些匹配项,即可轻松获得特定结果。以下将只为您提供包含特定 categories.categoryIdcategories.products.productId 的记录:

db.device.aggregate([{
    "$unwind": "$categories"
},{
    "$unwind": "$categories.products"
}, {
    $match: {
        "categories.categoryId": "201",
        "categories.products.productId": "301"
    }
}])

给你:

{
    "_id": "1",
    "name": "list 1",
    "categories": {
        "categoryId": "201",
        "products": {
            "productId": "301",
            "name": "product 1"
        }
    }
}

您可以添加$group 键以按_id 或其他任何方式分组。看https://docs.mongodb.com/manual/aggregation/

要删除子数组products 中的一项,也无需循环遍历结果,使用update 请求和pull,您可以在数组中准确找到您想要的内容并在一个请求中将其删除.

在以下请求中,我使用pullelemMatch 的结果定义的位置参数,因为您在另一个数组中有一个数组:

db.device.update({
    'categories': {
        '$elemMatch': {
            categoryId: '201'
        }
    },
    _id: '1'
}, {
    $pull: {
        'categories.$.products': {
            'productId': '301'
        }
    }
});

上面的查询将只删除包含productId 301 的元素,用于categoryId 201 和元素匹配_id=1

查看https://docs.mongodb.com/manual/reference/operator/update/pull/

【讨论】:

    【解决方案2】:

    是的,如果您不想在列表中获取categoriesproducts,您可以像通常使用SQL 数据库一样设计架构。像这样的:

    List
          {
               '_id':1,
               'name': 'groceries'  
            }
    
    Category
        {
          '_id':1,
          'listId': 1,
          'name': 'Cereal'
        }
    Product
        {
          '_id': 1,
          'name': 'Weetbix',
          'categoryId':1
        }
    

    这样做有助于您轻松管理数据。

    【讨论】:

      猜你喜欢
      • 2015-06-27
      • 2015-01-26
      • 2016-03-29
      • 1970-01-01
      • 2011-08-15
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      相关资源
      最近更新 更多