創(chuàng)建文檔
1.主鍵
MongoDB的主鍵和MySQL一樣, 也是用于保證每一條數(shù)據(jù)唯一性的
和MySQL不同的是, MongoDB中的主鍵無(wú)需明確指定
每一個(gè)文檔被添加到集合之后, MongoDB都會(huì)自動(dòng)添加主鍵
MongoDB中文檔主鍵的名稱叫做 _id
默認(rèn)情況下文檔主鍵是一個(gè)ObjectId類型的數(shù)據(jù)
ObjectId類型是一個(gè)12個(gè)字節(jié)字符串(5e8c5ae9-c9d35e-759b-d6847d)
4字節(jié)是存儲(chǔ)這條數(shù)據(jù)的時(shí)間戳
3字節(jié)的存儲(chǔ)這條數(shù)據(jù)的那臺(tái)電腦的標(biāo)識(shí)符
2字節(jié)的存儲(chǔ)這條數(shù)據(jù)的MongoDB進(jìn)程id
3字節(jié)是計(jì)數(shù)器
2.1為什么要使用ObjectId類型數(shù)據(jù)作為主鍵?
因?yàn)镸ongoDB是支持'橫向擴(kuò)展'的數(shù)據(jù)庫(kù)
橫向擴(kuò)展是指'增加數(shù)據(jù)庫(kù)服務(wù)器的臺(tái)數(shù)
縱向擴(kuò)展是指'增加數(shù)據(jù)庫(kù)庫(kù)服務(wù)器的配置'
過(guò)去一個(gè)數(shù)據(jù)庫(kù)只能安裝在一臺(tái)電腦上, 但是每臺(tái)電腦的性能是有峰值的一旦達(dá)到峰值就會(huì)導(dǎo)致服務(wù)器卡頓诉瓦、宕機(jī)限匣、重啟等問(wèn)題.
所以過(guò)去為了防止如上問(wèn)題的出現(xiàn),我們只能不斷的'縱向擴(kuò)展'
也就是不斷的提升服務(wù)器的配置, 讓服務(wù)器能處理更多的請(qǐng)求
但是縱向擴(kuò)展也是有峰值的, 一臺(tái)電腦的配置不可能無(wú)限提升
所以為了解決這個(gè)問(wèn)題就有了分布式數(shù)據(jù)庫(kù)
分布式數(shù)據(jù)庫(kù)是指可以在多臺(tái)電腦上安裝數(shù)據(jù)庫(kù), 然后把多臺(tái)電腦組合成一個(gè)完整的數(shù)據(jù)庫(kù),
在分布式數(shù)據(jù)庫(kù)中,我們可以通過(guò)不斷同步的方式, 讓多臺(tái)電腦都保存相同的內(nèi)容
當(dāng)用戶請(qǐng)求數(shù)據(jù)時(shí), 我們可以把請(qǐng)求派發(fā)給不同的數(shù)據(jù)庫(kù)服務(wù)器處理
當(dāng)某一臺(tái)服務(wù)器宕機(jī)后, 我們還可以繼續(xù)使用其它服務(wù)器處理請(qǐng)求
從而有效的解決了單臺(tái)電腦性能峰值和單臺(tái)電腦宕機(jī)后服務(wù)器不能使用的問(wèn)題
2.2為什么要使用ObjectId類型數(shù)據(jù)作為主鍵?
正是因?yàn)镸ongoDB是一個(gè)分布式數(shù)據(jù)庫(kù), 正是因?yàn)榉植际綌?shù)據(jù)庫(kù)可以把請(qǐng)求派發(fā)給不同的服務(wù)器
所以第一次插入數(shù)據(jù)時(shí), 我們可能派發(fā)給了A服務(wù)器, 插入到了A服務(wù)器的數(shù)據(jù)庫(kù)中
但是第二次插入數(shù)據(jù)時(shí), 我們又可能派發(fā)給了B服務(wù)器, 插入到了B服務(wù)器的數(shù)據(jù)庫(kù)中
但是B服務(wù)器此時(shí)并不知道A服務(wù)器當(dāng)前的主鍵值是多少, 如果通過(guò)MySQL中簡(jiǎn)單的遞增來(lái)保證數(shù)據(jù)的唯一性
那么將來(lái)在多臺(tái)服務(wù)器同步數(shù)據(jù)的時(shí)候就會(huì)出現(xiàn)重復(fù)的情況, 所以MongoDB的主鍵并沒(méi)有使用簡(jiǎn)單的遞增
而是使用了ObjectId類型數(shù)據(jù)作為主鍵
3.是否支持其它類型數(shù)據(jù)作為主鍵?
3.1在MongoDB中支持除了'數(shù)組類型'以外的其它類型數(shù)據(jù)作為主鍵
3.2在MongoDB中甚至還支持將一個(gè)文檔作為另一個(gè)文檔的主鍵(復(fù)合主鍵)
db.person.insert({name: 'css', age: 33});
db.person.insert({_id: 1, name: 'css', age: 33});
#db.person.insert({_id: 1, name: 'csss', age: 33}); #報(bào)錯(cuò)
db.person.insert({_id: '1', name: 'css', age: 33});
db.person.insert({_id: {name:'js', gender: '男'}, name: 'css', age: 33});
#db.person.insert({_id: {name:'js', gender: '男'}, name: 'css', age: 33}); #報(bào)錯(cuò)
db.person.insert({_id: {gender: '男', name:'js'}, name: 'css', age: 33});
寫(xiě)入文檔
1.寫(xiě)入一個(gè)文檔
db.<collection>.insertOne(
<document>,
{
writeConcern: <document>
}
);
document: 需要寫(xiě)入的文檔
writeConcern: 寫(xiě)入安全級(jí)別
2.安全級(jí)別
用于判斷數(shù)據(jù)是否寫(xiě)入成功,
安全級(jí)別越高, 丟失數(shù)據(jù)風(fēng)險(xiǎn)越小, 但是性能消耗(操作延遲)也就越大
默認(rèn)情況下MongoDB會(huì)開(kāi)啟默認(rèn)的安全些級(jí)別,先不用關(guān)心
3.注意點(diǎn)
在使用insertXXX寫(xiě)入文檔時(shí), 如果調(diào)用insertOne的集合不存在會(huì)自動(dòng)創(chuàng)建
db.person.insertOne({name:'zs', age:18})
db.person.find()
db.student.insertOne({name:'zs', age:18}) #集合不存在會(huì)自動(dòng)創(chuàng)建 db.student.find()
4.其它方式
db.<collection>.save(
? <document>,
? {
? writeConcern: <document>
? }
);
db.person.save({name:'ls', age:19})
db.person.find()
db.teacher.save({name:'ls', age:19}) #集合不存在會(huì)自動(dòng)創(chuàng)建
db.teacher.find()
5.insertOne和save不同
主鍵沖突時(shí)insertOne會(huì)報(bào)錯(cuò),而save會(huì)直接用新值覆蓋久值
db.person.insertOne({_id:1, name:'ww', age:22})
db.person.find()
db.person.insertOne({_id:1, name:'ww', age:22}) #報(bào)錯(cuò)
db.person.save({_id:1, name:'zs', age:66}) #用新數(shù)據(jù)替換久數(shù)據(jù)
db.person.find()
6.寫(xiě)入多個(gè)文檔
db.<collection>.insertMany(
? [<document>, ...],
? {
? writeConcern: <document>,
? ordered: <boolean>
? }
);
ordered: 是否按順序?qū)懭?/p>
ordered默認(rèn)取值是true, 也就是會(huì)嚴(yán)格按照順序?qū)懭?/p>
如果ordered是false, 則不會(huì)按照順序?qū)懭? 但寫(xiě)入效率更高(系統(tǒng)會(huì)自動(dòng)優(yōu)化)
db.person.insertMany(
[{name:'zs', age:18},{name:'ls', age:19},{name:'ww', age:20}],
{}
)
db.person.find()
注意點(diǎn):
如果ordered是true, 前面的文檔出錯(cuò), 后面的所有文檔都不會(huì)被寫(xiě)入
如果ordered是false, 前面的文檔出錯(cuò), 后面的所有文檔也會(huì)被寫(xiě)入
db.person.insertMany(
[{_id:1, name:'zs', age:18},{_id:1, name:'ls', age:19},{_id:2, name:'ww', age:20}],
{ ordered: true }
)
// 如果ordered:true, _id相同,那么后面數(shù)據(jù)不會(huì)插入
db.person.find()
db.person.remove({})
db.person.insertMany(
[{_id:1, name:'zs', age:18},{_id:1, name:'ls', age:19},{_id:2, name:'ww', age:20}],
{ ordered: false }
)
// 如果 order:false, _id相同, 后面的數(shù)據(jù)也會(huì)被插入
db.person.find()
7.Insert寫(xiě)入一個(gè)或多個(gè)文檔
db.<collection>.insert(
? <document> or ,[<document>, ...]
? {
? writeConcern: <document>,
? ordered: <boolean>
? }
);
insertOne和insertMany結(jié)合體
2.注意點(diǎn):
和insertOne/insertMany一樣, 集合不存在會(huì)自動(dòng)創(chuàng)建
和insertOne/insertMany一樣, 主鍵沖突會(huì)報(bào)錯(cuò)
和insertMany一樣, 默認(rèn)都是按順序插入, 前面的文檔出錯(cuò), 后續(xù)所有文檔不會(huì)被插入
刪除文檔
1.刪除文檔
db.<collection>.remove(<query>, <options>)
<query>: 刪除篩選條件
<options>: 刪除額外配置
2.示例
db.person.insert([
{name:'zs', age:18},
{name:'zs', age:19},
{name:'ls', age:20},
{name:'ls', age:21},
{name:'ww', age:22},
{name:'zl', age:23},
])
//2.1刪除所有滿足條件
// 注意點(diǎn): 和update方法不同, remove方法默認(rèn)就會(huì)刪除所有滿足條件的數(shù)據(jù)
db.person.remove({name:'zs'})
//2.2刪除第一個(gè)滿足條件
db.person.remove({name:'ls'},{justOne:true})
//2.3刪除所有文檔
db.person.remove({})