MongoDB 數據模型
MongoDB數據庫介紹
特點
- 面向集合存儲
- 豐富的查詢語句
- 復制集機制
- 支持文件存儲
- 模式自由
- 多級索引
- 易水平擴展
- 跨平臺、支持語言眾多
- 可插入式存儲引擎(3.0)
適用場景
- 數據緩存
- JSON格式的數據
- 局伸如性場景
- 弱事務類型業務
MongoDB更多適合於大數據量、高並發、弱事務的互聯網應用,其內置的水平擴展 機制提供了從幾百萬到十億級別的數據處理能力,可以很好的滿足Web2.0和移動互聯網應 用的數據存儲要求。
MongoDB的相關網站
官方文檔:https://docs.mongodb.com/tutorials/
中文網站:http://www.mongoing.com/
谷歌Group:https://groups.google.com/forum/
MongoDB概念解析
SQL術語/概念 | MongoDB術語/概念 | 解釋/說明 |
---|---|---|
database |
database |
數據庫 |
table |
collection |
數據庫表/集合 |
row |
document |
數據記錄行/文檔 |
column |
field |
數據字段/域 |
index |
index |
索引 |
table joins |
embedded documents/reference | 表連接/(內嵌/引用) |
primary key |
primary key |
主鍵,MongoDB自動將_id字段設置為主鍵 |
通過下圖實例,可以更直觀的的了解Mongo
中的一些概念:
數據庫
多個文檔組成集合,而多個集合組成了數據庫。一個MongoDB實例可以 承載多個數據庫,每個數據庫都有獨立的權限,在磁盤上,不同的數據庫也 可放置在不同的文件夾中(啟動時加directoryperdb選項)。
為了更好的組織數據,一般情況下,會把屬於同一個應用程序(或同一種 業務類型)的所有數據放到一個數據庫中。
show dbs
命令可以顯示所有數據的列表。
? at [09/10/17][0:21:00]
? ? mongo
MongoDB shell version: 3.2.11
connecting to: test
> exit
bye
? at [09/10/17][0:21:04]
? ? mongo
MongoDB shell version: 3.2.11
connecting to: test
> show dbs
local 0.000GB
執行 "db" 命令可以顯示當前數據庫對象或集合。
> db
test
運行use db_name
命令,切換數據庫,沒有數據庫時自動創建
> use local
switched to db local
> db
local
>
以上實例命令中,local
是你要鏈接的數據庫。
在下一個章節我們將詳細講解MongoDB
中命令的使用。
數據庫也通過名字來標識。數據庫名可以是滿足以下條件的任意UTF-8字符串。
- 不能是空字符串("")。
- 不得含有‘ ‘(空格)、.、$、/、\和\0 (空字符)。
- 數據庫名字區分大小寫(建議數據庫名全部使用小寫)
- 最多64字節。
- 不要與系統保留的數據庫名字相同,這些數據庫包括:admin、local、 config等
有一些數據庫名是保留的,可以直接訪問這些有特殊作用的數據庫。
- admin: 從權限的角度來看,這是"root"數據庫。要是將一個用戶添加到這個數據庫,這個用戶自動繼承所有數據庫的權限。一些特定的服務器端命令也只能從這個數據庫運行,比如列出所有的數據庫或者關閉服務器。
- local: 這個數據永遠不會被復制,可以用來存儲限於本地單臺服務器的任意集合
- config: 當
Mongo
用於分片設置時,config
數據庫在內部使用,用於保存分片的相關信息。
相關操作
命令 | 操作 |
---|---|
db |
查看當前數據庫 |
show dbs |
查看當前端口有多少數據庫 |
use db_name |
切換數據庫,沒有數據庫時自動創建 |
db.dropDatabase() |
刪除數據庫 |
文檔
文檔是MongoDB最核心的概念,本質上是一種類JSON的BSON格式的數據。
BSON是一種類JSON的二進制格式數據,它可以理解為在JSON基礎上添加了 _些新的數據類型,包括曰期、int32、int64等。
BSON是由一組組鍵值對組成,它具有輕量性、可遍 歷性和高效性三個特征。可遍歷性是MongoDB將BSON 作為數據存儲的主要原因。
BSON官網地址:http://bsonspec.org/
{
fieldl:valuel,
field2:value2,
field3:value3,
...
fieldN:valuen
}
下表列出了 RDBMS
與 MongoDB
對應的術語:
RDBMS | MongoDB |
---|---|
數據庫 | 數據庫 |
表格 | 集合 |
行 | 文檔 |
列 | 字段 |
表聯合 | 嵌入文檔 |
主鍵 | 主鍵 (MongoDB 提供了 key 為 _id ) |
數據庫服務 | 客戶端 |
---|---|
Mysqld /Oracle |
mysql /sqlplus |
mongod |
mongo |
需要註意的是:
- 文檔中的鍵/值對是有序的。MongoDB會盡量保持文檔被插入時鍵值對的順序
- 文檔中的值不僅可以是在雙引號裏面的字符串,還可以是其他幾種數據類型(甚至可以是整個嵌入的文檔)。
- MongoDB區分類型和大小寫。
- MongoDB的文檔不能有重復的鍵。
- 文檔的鍵是字符串。除了少數例外情況,鍵可以使用任意UTF-8字符。
- MongoDB中寫操作的原子性限制在文檔級別,對文檔的保存、修改、刪除 等都是原子操作
- 單個文檔占用的存儲空間不能超過16MB
關於文檔鍵的命名需要註意以下幾點:
- _id是系統保留的關鍵字,它是默認的主鍵,該值在集合中必須唯一,且不可更改
- .(命名空間)和$(操作符)有特別的意義,只有在特定環境下才能使用。
- 以下劃線"_"開頭的鍵是保留的(不是嚴格要求的)。
- 鍵不能包含\0或空字符,這個字符用於表示鍵的結尾
- 鍵是區分大小寫的且不能重復例如:{foo:l,Foo:l}
內嵌文檔
文檔可以作為鍵的值,這樣的文檔稱為內嵌文檔。內嵌文檔可以使數據不用保存成扁平結構的鍵值對,從而使數據組織方式更加自然。
例如:下面是一個與博客管理有關的文檔
{
_id: <Objectldl>,
title: MongoDBDateModeln,
author: foo,
comments:[
{who:"John",comment:"Good"},
{who:"Joe",comment:"ExceUent"}
]
}
上面的文檔可以進行如下的拆分:
即拆分成引用文檔.
內嵌文檔特點
- 子文檔比較少時,可以保證原子性,同時具備高速查詢;
- 子文檔比較多時,會影響查詢和更新速度,同時也帶來數據冗余
集合
把一組相關的文檔放到一起組成了集合,如果將MongoDB的一個文檔比喻 為關系型數據庫中的一行,那麽一個集合就相當於一張表。
MongoDB的集合是模式自由的,一個集合裏面的文檔可以是各式各樣。
例如:下面的兩個文檔可以出現了同一個集合中。
{"x":1}
{"x":1,"y":2}
{"x":1,"y":2,"z":5}
當第一個文檔插入時,集合就會被創建。
MongoDB提供了一些特殊功能的集合,例如:cappedcollection、 system.indexes、system.namespaces 等。
合法的集合名
- 集合名不能是空字符串""。
- 集合名不能含有
\0
字符(空字符),這個字符表示集合名的結尾。 - 集合名不能以
system.
開頭,這是為系統集合保留的前綴。 - 用戶創建的集合名字不能含有保留字符。有些驅動程序的確支持在集合名裏面包含,這是因為某些系統生成的集合中包含該字符。除非你要訪問這種系統創建的集合,否則千萬不要在名字裏出現$(註:可包含.)
如下實例:
db.col.findOne()
capped collections
Capped collections 就是固定大小的collection。
它有很高的性能以及隊列過期的特性(過期按照插入的順序). 有點和 "RRD" 概念類似。
Capped collections是高性能自動的維護對象的插入順序。它非常適合類似記錄日誌的功能 和標準的collection不同,你必須要顯式的創建一個capped collection, 指定一個collection的大小,單位是字節。collection的數據存儲空間值提前分配的。
要註意的是指定的存儲大小包含了數據庫的頭信息。
db.createCollection("mycoll", {capped:true, size:100000})
- 在capped collection中,你能添加新的對象。
- 能進行更新,然而,對象不會增加存儲空間。如果增加,更新就會失敗 。
- 數據庫不允許進行刪除。使用drop()方法刪除collection所有的行。
- 註意: 刪除之後,你必須顯式的重新創建這個collection。
- 在32bit機器中,capped collection最大存儲為1e9( 1X109)個字節。
命名空間
把數據庫名添加到集合名字前面,中間用點號連接,得到集合的完全限定 名,就是命名空間,例如:命名空間parent.sub。
需要說明的是,點號還可以出現在集合名字中,例如:parent.subling0,parent.subling2可以將subling0和subling2集合看作是parent集合的子集合。
使用子集合可以使我們更好的組織數據,使數據的結構更加清晰明了。
元數據
數據庫的信息是存儲在集合中。它們使用了系統的命名空間:
dbname.system.*
在MongoDB數據庫中名字空間<dbname>.system.*
是包含多種系統信息的特殊集合(Collection),如下:
集合命名空間 | 描述 |
---|---|
db.system.namespaces |
列出所有名字空間。 |
db.system.indexes |
列出所有索引。 |
db.system.profile |
包含數據庫概要(profile)信息。 |
db.system.users |
列出所有可訪問數據庫的用戶。 |
db.local.sources |
包含復制對端(slave)的服務器信息和狀態。 |
對於修改系統集合中的對象有如下限制。
在{{system.indexes}}
插入數據,可以創建索引。但除此之外該表信息是不可變的(特殊的drop index命令將自動更新相關信息)。
{{system.users}}
是可修改的。 {{system.profile}}
是可刪除的。
MongoDB 數據類型
BSON可以理解為在JSON基礎上添加了一些新的數據類型,包括Date,正貝IJ 表達式,對數值類型的更進一步劃分等。
數據類型 | 類型編號 | 數據類型 | 類型編號 |
---|---|---|---|
Double | 1 | Regular Expression | 11 |
String | 2 | JavaScript | 13 |
Object | 3 | Symbol | 14 |
Array | 4 | JavaScript(Scope) | 15 |
Binarydata | 5 | 32-bit integer | 16 |
Object id | 7 | Timestamp | 17 |
Boolean | 8 | 64-bit integer | 18 |
Date | 9 | Min Key | 255 |
Null | 10 | Max Key | 127 |
可以使用類型編號進行條件查詢如下:
db.collection.find({name:{$type:2}})
基本數據類型
null 表示空值或不存在的字段例如:db.collection.find({nyn:null})
- 布爾有兩個值true或false 例如:{"y":true}
數值類型支持32-int、64-int以及64-double
註:JavaScript只支持64位浮點數
例如:
- {"y":10} - double
- {"y":Numberlnt(10)} - 32
- {"y":NumberLong(10)} - 64
7 Documents:0 > db.demo.insert({y:10}) WriteResult({ "nInserted" : 1 }) 8 Documents:1 > db.demo.find({y:{$type:1}}) { "_id" : ObjectId("5a7863305640374fb2cd5620"), "y" : 10 } 9 Documents:1 > db.demo.insert({y:NumberInt(10)}) WriteResult({ "nInserted" : 1 }) 10 Documents:2 > db.demo.find({y:{$type:16}}) { "_id" : ObjectId("5a78636d5640374fb2cd5621"), "y" : 10 } 11 Documents:2 > db.demo.insert({y:NumberLong(10)}) WriteResult({ "nInserted" : 1 }) 12 Documents:3 > db.demo.find({y:{$type:18}}) { "_id" : ObjectId("5a7863915640374fb2cd5622"), "y" : NumberLong(10) }
- 字符串使用UTF-8對字符串進行編碼例如:{"y":"HelloMongoDB"}
二進制數據可以保存由任意字節組成的字符串,例如:圖片、視頻等
正則表達式:主要用於查詢,使用正則表達式作為限定條件
例如:
- {name:/foo/} name字段含有foo的文檔
- {name:/foo/i} name字段含有foo的文檔,且不區分大小寫
- {name:/^foo/i} name字段以foo幵頭,且不區分大小寫
JavaScript代碼:文檔中可以包含任意的JavaScript代碼
例如:{"func":function(){}}
Date日期
- MongoDB中,日期類型是一個64位的整數,它代表的是距Unixepoch的毫秒數
- MongoDB在存儲時間時,先轉化為UTC時間
- 北京時間(CST) = UTC + 8個小時
- MongoDBShell中可以使用newDate或ISODate來創建時間對象,在進行顯示時,Shell會根據本地時間去設置顯示日期對象
14 Documents:3 > var mydate0 = new Date()
15 Documents:3 > var mydate9 = ISODate()
16 Documents:3 > mydate0
ISODate("2018-02-05T14:04:43.243Z")
17 Documents:3 > mydate9
ISODate("2018-02-05T14:04:57.715Z")
18 Documents:3 > mydate9.toString()
Mon Feb 05 2018 22:04:57 GMT+0800 (CST)
Timestamp
- 時間戳類型有兩部分組成:
- Timestmp只供MongoDB數據庫服務內部使用,用於記錄操作的詳細時間
- Timestamp類型和Date類型是沒有關系的,對於我們來說使用更多的Date類型
- 相關函數:Timestamp()
Objectld
Objectld由24個十六進制字符構成,每個字節存儲兩位十六進制數字,總共需 12字節存儲空間
每個字節代表的含義如下:
這種方式生成的Objectld在分布式仍然是唯一的.
相關函數:
Objectld()
用於取得Objectld
getTimestamp()
用於取得Objectld的時間戳
valueOf()
用於取得Objectld的字符串表示
19 Documents:3 > x = ObjectId()
ObjectId("5a7866e75640374fb2cd5623")
20 Documents:3 > x.getTimestamp()
ISODate("2018-02-05T14:15:03Z")
21 Documents:3 > x.valueOf()
5a7866e75640374fb2cd5623
數組
數組是使用方括號來表示的一組值,它既可以作為有序對象(列表、棧、隊 歹|J),也能作為無序對象(如集合)來操作
數組中可以包含不同數據類型的元素(字符串、浮點數、文檔等)
例如:[3.14,"hello",[l2,3],{"key":"MongoDB"}]
針對數組MongoDB提供了許多特定的操作符,例如:
$push
,$pop
,$pull
,$slice
,$addToSet
等MongoDB可自動的為數組元素建立Multikey索引
MongoDB 數據模型