資料結構與關聯:文件如何結構化
Resetting Your Database
刪除資料庫
步驟一:先切換至欲刪除的資料庫
$ use dbName
步驟二:輸入刪除指令
$ db.dropDatabase()
刪除 Collection
步驟一:先確認目前有哪些 Collection
$ show collections
步驟二:輸入刪除指令
$ db.collectionName.drop()
Structuring Documents
以下列出 MongoDB 可接受的三種資料結構
雜亂無章
[
{
"name": "Apple",
"price": 2
},
{
"title": "Box",
"currency": "USD"
},
{
"name": "Jack",
"isAdmin": true
}
]
結構相同
[
{
"name": "Apple",
"price": 2.25,
"discount": null
},
{
"name": "Box",
"price": 3.99,
"discount": false
},
{
"name": "Car",
"price": 99999,
"discount": true
}
]
保有彈性
[
{
"name": "Apple",
"price": 2.25
},
{
"name": "Box",
"price": 3.99
},
{
"name": "Car",
"price": 99999,
"discount": true
}
]
Data Types - An Overview
MongoDB 的資料型別
- Text
使用上沒什麼限制,最高容量為 16 MB。 - Boolean
- Number
細分為 int32、int64、decimal - ObjectId
基於 timestamp 而自動生成的 ID,因此同一批次寫入的資料會是連號 ID。 - ISODate
ISODate("2020-02-02") - Timestamp
Timestamp(11421532) - Embedded Document
- Array
- Number in mongosh 在 Node.js Driver 的 mongosh 當中,數字皆以 float64 存取。
Data Types in Action
在 mongosh 當中可使用 Driver 對應的語言的各種函式,詳情可參考官方文件。
$ db.companies.insertOne({foundingDate: new Date(), insertedAt: new Timestamp()})
mongosh Methods
在 mongosh 當中有許多方法可使用,點擊標題連結可檢視官方文件說明。
- db.stats()
這個方法可以檢視資料庫的統計資料(statistics)。
{
db: 'numbers',
collections: 1,
views: 0,
objects: 1,
avgObjSize: 29,
dataSize: 29,
storageSize: 20480,
indexes: 1,
indexSize: 20480,
totalSize: 40960,
scaleFactor: 1,
fsUsedSize: 58829078528,
fsTotalSize: 250685575168,
ok: 1
}
- NumberInt()
NumberInt() 用於插入資料時,如此將以 int32 的型別插入數值。
$ db.collection_name.insertOne({a: NumberInt(1)})
- typeof
使用 typeof 可確認資料型別
$ typeof db.collection_name.findOne({key: value}).key
Data Types & Limits
值得注意的資料型別限制
- 普通整數(int32)
可儲存範圍為 +-2,147,483,647 - 長整數(int64)
可儲存範圍為 +-9,223,372,036,854,775,807 - 文字(text)
長度不限,但容量不得超過 Document 上限(16MB)
在 mongosh 當中
NumberInt 建立 int32 數值 => NumberInt(55) NumberLong 建立 int64 數值 => NumberLong(7489729384792)
由於 shell 以 JavaScript 為基礎,而 JavaScript 只有浮點數及倍精度數值,不區分整數及浮點數, 因此插入資料時如果只填入數字(例如 insertOne({a: 1}),該數字將以普通的浮點數儲存至資料庫。
NumberDecimal 可建立高精度浮點數值 => NumberDecimal("12.99")
此方法適用於極度講求精確度的計算。
使用 MongoDB 驅動程式(而非 shell)編寫應用程式時(例如 PHP、.NET、Node.js 等)時,
可以使用驅動程式建立上述特殊數值。
以 Node.js 為例:http://mongodb.github.io/node-mongodb-native/3.1/api/Long.html
以下是透過驅動程式建立 NumberLong 值的範例:
const Long = require("mongodb").Long;
db.collection("wealth").insert({
value: Long.fromString("121949898291"),
});
檢視各驅動程序的 API 文件,可找到建立 int32、int64 等數值的方法。
How to Derive your Data Structure - Requirements
Using "lookUp()" for Merging Reference Relations
Adding Collection Document Validation
使用 createCollection 方法及 $jsonSchema 可建立含有資料驗證的 Collection,
其使用方法見下列官方文件。
以下指令可檢視 Collection 有何資料驗證設定
$ db.getCollectionInfos({name:"collection_name"})
Changing the Validation Action
使用 runCommand 方法及 collMod 可修改 Collection 的資料驗證規則,
其使用方法見下列官方文件。
db.runCommand({
collMod: "collection_name",
validator: {
$jsonSchema: {
// add schema
},
/*
validationAction option, which determines whether MongoDB should error and reject
documents that violate the validation rules or warn about the violations in
the log but allow invalid documents.
*/
validationAction: "warn",
},
});
Wrap Up
資料結構的設計考量
- In which format will you fetch your data?
根據讀取或寫入的需求設計資料結構 - How often will you fetch and change your data?
思考讀取或寫入的頻率、何者更應該優化
如果經常寫入資料,應該避免資料重複。
如果資料不常更動,且經常讀取,或可允許少量重複。 - How much data will you save (and how big is it)?
嵌入式結構不適合儲存海量資料 - How is your data related?
從一對一、一對多、多對多思考是否使用嵌入式結構 - Will duplicates hurt you ( => many updates)?
如果資料需要頻繁更新,該資料應避免重複。
如果重複的資料不需全面同步更新,或許可以允許資料重複。(例如 snapshot data) - Will you hit data / storage limits?