zoukankan      html  css  js  c++  java
  • MongoDB实战读书笔记(二):面向文档的数据

    1 schema设计原则

    1.1 关系型数据库的三大设计范式

    • 第一范式(1NF)无重复的列
    • 第二范式(2NF)属性完全依赖于主键 [ 消除部分子函数依赖 ]
    • 第三范式(3NF)属性不依赖于其它非主属性 [ 消除传递依赖 ]

    参考:https://blog.csdn.net/zhangminemail/article/details/56834253

    1.2 选择Mongodb需要考虑

    • 读写比例、查询语句是否复杂、是否需要聚合函数、数据量
    • 数据基本单位是什么
      • RDBMS:表
      • 键值数据库:键指向的值
      • Mongodb:BSON文档
    • 是否需要强事务支持
    • 如何记录生成好的唯一ID或者主键,如:RDMS支持联合主键

    1.3 schema基础

    (1)文档设计

    // 商品
    {
    	_id: ObjectId("4c4b1476238d3b4dd5003981"), // 唯一ID
        slug:"wheelbarrow-9092", // 唯一slug
        sku:"9092",
        name:"Extra Large wheelbarrow",
        description:"Heav y duty wheelbarrow...",
        details:{ // 嵌套文档
            weight:47,
            wight_units:"lbs",
            model_num: 4039283402,
            manufacturer:"Acme",
            color:"green"
        },
        total_reviews:4,
        average_review:4.5,
        pricing:{
            retail:589700,
            sale:489700
        },
        price_history:[{ 
            retail:529700,
            sale:429700,
            start:new Date(2010,4,1),
            end:new Date(2010,4,8)
        },{
            retail:529700,
            sale:529700,
            start:new Date(2010,4,9),
            end:new Date(2010,4,16)
        }],
        primary_category: ObjectId("6a5b1476238d3b4dd5000048"), // 一对多
        category_ids:[ // 多对多
            ObjectId("6a5b1476238d3b4dd5000048"),
            ObjectId("6a5b1476238d3b4dd5000049")
        ],
        main_cat_id:  ObjectId("6a5b1476238d3b4dd5000048"),
        tags:["tools","gardening","soil"]
    }
    

    (2)唯一slug

    // http://domain.com/products/4c4b1476238d3b4dd5003981
    
    // 展示相对友好一些
    // http://domain.com/products/wheelbarrow-9092
    
    db.products.createIndex({slug:1},{unique:true});
    

    (3)内嵌文档

    一般用于需要动态修改的内容

    如:details为商品详情,每个商品包含的信息不一样。如果是U盘,还需要标识内存大小;如果是桌子,需要标识高度等。

    (4)一对多

    一个商品只对应一个主要类别,一个类别下有多个商品

    (5)多对多

    一个商品对应多个关联类别,一个类别有多个商品

    (6)关系结构

    类别文档可以复用,所以我们需要把它提取出来,而不是像商品信息那样直接嵌套在商品中。

    // 类别文档  Home -> Outdoors -> Gardening Tools
    {
        _id: ObjectId("6a5b1476238d3b4dd5000048"), // Outdoors的子类别
        slug:"gardening-tools",
        name:"Gardening Tools",
        description:"Gardening gadgets glore!",
        parent_id: ObjectId("55804822812cb336b78728f9"),
        // 冗余数据,用于快速查找
        ancestors:[{
            name:"Home", // 商品类别
            _id:ObjectId("55804822812cb336b78728fa"),
            slug:"home"
        },{
            name:"Outdoors", // Home的子类别
            _id:ObjectId("55804822812cb336b78728f9"),
            slug:"outdoors"
        }]
    }
    

    (7)查询

    // 查询该类别的所有商品
    db.products.find({category_ids:ObjectId("6a5b1476238d3b4dd5000048")})
    
    // 查询商品的所有类别信息
    db.categories.find({_id:{$in:product['category_ids']}})
    
    db.products.findOne({'slug':'wheelbarrow-9092'})
    

    1.4 用户和订单:一个用户多个订单

    (1)订单

    // 订单
    {
        _id:ObjectId("6a5b1476238d3b4dd5000118"),
        user_id:ObjectId("4c4b1476238d3b4dd5003981"), // 用户ID
        state:"CART",
        line_items:[{
            _id:ObjectId("4c4b1476238d3b4dd5003981"),
            sku:"9092",
            name:"Extra Large Wheelbarrow",
            quantity:1,
            pricing:{
                retail:5897,
                sale:4897
            }
        },{
            _id:ObjectId("4c4b1476238d3b4dd5003982"),
            sku:"10027",
            name:"Rubberized Work Glove, Black",
            quantity:2,
            pricing:{
                retail:1499,
                sale:1299
            } 
        }],
        shipping_address:{
            street:"588 5th",
            city:"Brooklyn",
            state:"NY",
            zip:11215
        },
        sub_total:6196
    }
    

    (2)用户

    {
    	_id:ObjectId("4c4b1476238f3b4dd5000042"),
        username:"test",
        email:"test@test.com",
        first_name:"Kyle",
        last_name:"Banker",
        hashed_password:"bd1cfa194c3a603e7186780824b04419",
        addresses:[{
            name:"home",
            street:"588 5th",
            city:"Brooklyn",
            state:"NY",
            zip:11215
        },{
            name:"word",
            street:"1 E. 23th",
            city:"New York",
            state:"NY",
            zip:10010
        }],
        payment_methods:[{
            name:"VISA",
            payment_token:"43f6ba6b8106fc7"
        }]
    }
    

    (3)查询操作

    // 查询用户的所有订单
    db.orders.find({user_id:user['_id']})
    
    // 查询订单的用户信息
    db.users.findOne({_id:orders['user_id']})
    

    1.5 评价

    {
        _id: ObjectId("4c4b1476238d3b4dd5000041"),
        product_id: ObjectId("4c4b1476238d3b4dd5003981"),
        date: new Date(2010,5,7),
        title:'Amazing',
        text:'Amzing.I love it.',
        rating:4,
        user_id: ObjectId("4c4b1476238f3b4dd5000042"),
        username: "dgreethumb",
        helpful_votes:3,
        voter_ids:[ // 评论者的用户ID,阻止多次投票
            ObjectId("4c4b1476238f3b4dd5000133"),
            ObjectId("4c4b1476238f3b4dd5000003"),
            ObjectId("4c4b1476238f3b4dd5001032")
        ]
    }
    

    2 核心概念:数据库、集合、文档

    2.1 数据库

    (1)数据库是集合和索引的命名空间和物理分组

    (2)管理数据库

    // 使用garden数据库
    > use garden
    
    // 删除当前数据库
    > db.dropDatabase()
    
    // 数据库当前状态
    > db.stats()
    {
        "db": "garden",
        "collections": NumberInt("4"),
        "views": NumberInt("0"),
        "objects": NumberInt("477985"),
        "avgObjSize": 178.613015052774,
        "dataSize": 85374342, // 数据库实际BSON大小
        "storageSize": 30539776,// 额外的为集合增长预留的空间
        "numExtents": NumberInt("0"),
        "indexes": NumberInt("9"),
        "indexSize": 10194944, // 索引总大小
        "ok": 1
    }
    

    2.2 集合

    (1)集合是结构或概念上相似的文档的容器。

    (2)管理集合

    // 显式创建集合
    db.createCollection("users");
    // 显式创建集合并指定分配空间的大小(字节)
    db.createCollection("users",{size:20000});
    
    // 集合名不能超过128个字符
    
    // 重命名集合
    db.products.renameCollection("store_products");
    

    (3)固定集合

    • 指定集合的大小和集合的容量,类似一个队列,满了之后新的数据进来,最久的数据出去
    // Max size:16384kB 数量:100
    > db.createCollection("users.actions",{capped:true,size:16384,max:100})
    

    (4)TTL集合

    • MongoDb允许在特定的时间后废弃文档数据。
    // 一分钟失效,依赖索引机制
    > db.reviews.createIndex({time_field:1},{expireAfterSeconds:3600})
    

    (5)系统集合

    > db.system.users.find()
    
    > db.system.version.find()
    

    2.3 文档

    (1)类型

    • 字符串:UTF-8编码,不能由$开始,不包含圆点、不能包含null字节
    • 数字:double、int、long
    • 时间:从Unix纪元计时开始时间值使用64b整数的毫秒表示
    • 虚拟类型:
    // 配合应用程序的converter进行转换
    // 参考:https://www.cnblogs.com/linzhanfly/p/9578738.html
    {
        time_with_zone:{
            time:new Date(),
            zone:"EST"
        }
    }
    

    (2)限制

    • BSON文档大小限制为16MB

    • 文档嵌套深度最大为100

    • 插入操作上限为16MB,即如果插入100W条数据需要分割为多个大量插入的文档组。

  • 相关阅读:
    离散数学知识点总结(8)-图论
    离散数学知识点总结(7)-格
    离散数学知识点总结(6)-计数技术
    离散数学知识点总结(5)函数
    离散数学知识点总结(4)-集合
    离散数学知识点总结(3)-二元关系
    离散数学知识点总结(2)-谓词逻辑
    离散数学知识点总结(1)-命题逻辑
    镜像仓库和Harbor
    视频管理上云平台EasyNVS 2.1版本分享RTSP流和RTMP流端口发生变化是什么原因?
  • 原文地址:https://www.cnblogs.com/linzhanfly/p/9719320.html
Copyright © 2011-2022 走看看