Big Data Technology / NoSQL Databases / Safari & Study

NoSQL | Exercises for Chap 4 – Document Databases




NoSQL数据库的四大分类表格分析

分类 Examples举例 典型应用场景 数据模型 优点 缺点
键值(key-value)[3]  Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。[3]  Key 指向 Value 的键值对,通常用hash table来实现[3]  查找速度快 数据无结构化,通常只被当作字符串或者二进制数据[3] 
列存储数据库[3]  Cassandra, HBase, Riak 分布式的文件系统 以列簇式存储,将同一列数据存在一起 查找速度快,可扩展性强,更容易进行分布式扩展 功能相对局限
文档型数据库[3]  CouchDB, MongoDb Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) Key-Value对应的键值对,Value为结构化数据 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 查询性能不高,而且缺乏统一的查询语法。
图形(Graph)数据库[3]  Neo4J, InfoGrid, Infinite Graph 社交网络,推荐系统等。专注于构建关系图谱 图结构 利用图结构相关算法。比如最短路径寻址,N度关系查找等 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。[3]

参考:https://blog.csdn.net/cangchen/article/details/44830087



文档数据库与传统的关系数据库差异显著。

关系数据库通常将数据存储在相互独立的表中,这些表由程序开发者定义,一个单一的对象可能散布在若干表中。 对于一个给定对象,文档数据库将其所有信息存储在数据库内某个单一实例中,并且存储的每一个对象可以不同于任一其它对象。这简化了将对象装加载数据库的过程,通常能消除对对象关系映射等类似方案的需求。

文档数据库不同于关系数据库,关系数据库基于了关系模型,而文档数据库采用了半结构化模型,没有在数据和模式(schema)之间的分离,使用的结构的数量依赖于目标用途。在半结构化数据中,属于相同类的实体可有不同的属性,即使它们被分组在一起,并且属性的次序是不重要的。















MongoDB表示文档数据之间关系的设计方法:

一、文档之间通过_id引用的方式关联

  • 文档可嵌套——子文档
  • 大文档分解 1 :
    • 经常访问的field
    • 不经常访问的field
  • 大文档分解 2

    首先”1对多”再”分类”

    • product collection ( including recent 10 reviews )
    • review collection
  • 对于 各个文档都有若干个相同的key-value 的情况:

    文档引用

    • 方法1 :publisher文档引用book文档

      问题:数据长度变化

    • 方法2 :book文档引用publisher文档

      问题:避免 数据长度变化

  • 时序文档数据模型设计:

    The Bucket Pattern 分桶优化模式 “分组”

时序文档:各个文档都有若干个相同结构的key-value,但是“时间”不同

二、DBRef,可以跨库关联相关文档

参考:https://www.runoob.com/mongodb/mongodb-relationships.html

MongoDB 关系

MongoDB 的关系表示多个文档之间在逻辑上的相互联系。

文档间可以通过嵌入和引用来建立联系。

MongoDB 中的关系可以是:

  • 1:1 (1对1)
  • 1: N (1对多)
  • N: 1 (多对1)
  • N: N (多对多)

    接下来我们来考虑下用户与用户地址的关系。

    一个用户可以有多个地址,所以是一对多的关系。

    以下是 user 文档的简单结构:

    {
    “_id”:ObjectId(“52ffc33cd85242f436000001”),
    “name”: “Tom Hanks”,
    “contact”: “987654321”,
    “dob”: “01-01-1991”
    }

    以下是 address 文档的简单结构:

    {
    “_id”:ObjectId(“52ffc4a5d85242602e000000”),
    “building”: “22 A, Indiana Apt”,
    “pincode”: 123456,
    “city”: “Los Angeles”,
    “state”: “California”
    }

    嵌入式关系

    使用嵌入式方法,我们可以把用户地址嵌入到用户的文档中:

    {
    “_id”:ObjectId(“52ffc33cd85242f436000001”),
    “contact”: “987654321”,
    “dob”: “01-01-1991”,
    “name”: “Tom Benzamin”,
    “address”: [
    {
    “building”: “22 A, Indiana Apt”,
    “pincode”: 123456,
    “city”: “Los Angeles”,
    “state”: “California”
    },
    {
    “building”: “170 A, Acropolis Apt”,
    “pincode”: 456789,
    “city”: “Chicago”,
    “state”: “Illinois”
    }]
    }

    以上数据保存在单一的文档中,可以比较容易的获取和维护数据。 你可以这样查询用户的地址:

    >db.users.findOne({“name”:“Tom Benzamin”},{“address”:1})

    注意:以上查询中 db 和 users 表示数据库和集合。

    这种数据结构的缺点是,如果用户和用户地址在不断增加,数据量不断变大,会影响读写性能。

    引用式关系

    引用式关系是设计数据库时经常用到的方法,这种方法把用户数据文档和用户地址数据文档分开,通过引用文档的 id 字段来建立关系。

    {
    “_id”:ObjectId(“52ffc33cd85242f436000001”),
    “contact”: “987654321”,
    “dob”: “01-01-1991”,
    “name”: “Tom Benzamin”,
    “address_ids”: [
    ObjectId(“52ffc4a5d85242602e000000”),
    ObjectId(“52ffc4a5d85242602e000001”)
    ]
    }

    以上实例中,用户文档的 address_ids 字段包含用户地址的对象id(ObjectId)数组。

    我们可以读取这些用户地址的对象id(ObjectId)来获取用户的详细地址信息。

    这种方法需要两次查询,第一次查询用户地址的对象id(ObjectId),第二次通过查询的id获取用户的详细地址信息。

    >var result = db.users.findOne({“name”:“Tom Benzamin”},{“address_ids”:1})
    >var addresses = db.address.find({“_id”:{“$in”:result[“address_ids”]}})


    参考:Mongodb架构设计浅谈

    https://juejin.im/post/5a0e370cf265da430d579392


    //movie_collection
    {
    “_id”: 1,
    “title”: “哪吒之魔童降世“,
    “year”: 2019,
    “running_time”: “110 min”,
    “released”: [ {“date”: ISODate(“2019-07-26”), “loc”: “中国大陆“},
    {“date”: ISODate(“2019-07-13”), “loc”: “大规模点映“} ],
    “type”: “movie”,
    “directors”: “饺子“,
    scriptwriter“: [“饺子“, “易巧“, “魏芸芸“],
    “main_cast”: [“吕艳婷“, “囧森瑟夫“, “翰墨“, “陈浩“, “绿绮“],
    “genres”: [“Drama”, “Comedy”, “Cartoon”, “Fantasy”],
    “producer_loc”: “China mainland”,
    “language”: “Mandarin”,
    “alias”: [“哪吒降世“, “Ne Zha”, “Nezha: Birth of the Demon Child”]
    }

    //movie_details_collection
    {
    “_id”: 155,
    “movie_id”: 1,
    “poster”: “http://….jpg“,
    “plot”: “天地灵气孕育出……“,
    “IMDb_link”: “tt10627720”,
    “douban”: {“rating”: 8.6, “num_reviews”: 926892,
    “5_stars”: “47.7%”, “4_stars”: “37.5%”, “3_stars”: “12.6%”,
    “2_stars”: “1.7%”, “1_star”: “0.6%”,
    “better_than_cartoons”: “89%”, “better_than_comedies”: “96%”}
    }


发表评论