您好,登錄后才能下訂單哦!
這篇文章主要介紹一篇文章教會你如何操作MongoDB,文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!
MongoDB是一款強(qiáng)大、靈活、且易于擴(kuò)展的通用型數(shù)據(jù)庫。
MongoDB是一個面向文檔(document-oriented)的數(shù)據(jù)庫,而不是關(guān)系型數(shù)據(jù)庫。 不采用關(guān)系型主要是為了獲得更好得擴(kuò)展性。當(dāng)然還有一些其他好處,與關(guān)系數(shù)據(jù)庫相比,面向文檔的數(shù)據(jù)庫不再有“行“(row)的概念取而代之的是更為靈活的“文檔”(document)模型。 通過在文檔中嵌入文檔和數(shù)組,面向文檔的方法能夠僅使用一條記錄來表現(xiàn)復(fù)雜的層級關(guān)系,這與現(xiàn)代的面向?qū)ο笳Z言的開發(fā)者對數(shù)據(jù)的看法一致。 另外,不再有預(yù)定義模式(predefined schema):文檔的鍵(key)和值(value)不再是固定的類型和大小。由于沒有固定的模式,根據(jù)需要添加或刪除字段變得更容易了。通常由于開發(fā)者能夠進(jìn)行快速迭代,所以開發(fā)進(jìn)程得以加快。而且,實(shí)驗(yàn)更容易進(jìn)行。開發(fā)者能嘗試大量的數(shù)據(jù)模型,從中選一個最好的。
應(yīng)用程序數(shù)據(jù)集的大小正在以不可思議的速度增長。隨著可用帶寬的增長和存儲器價格的下降,即使是一個小規(guī)模的應(yīng)用程序,需要存儲的數(shù)據(jù)量也可能大的驚人,甚至超出 了很多數(shù)據(jù)庫的處理能力。過去非常罕見的T級數(shù)據(jù),現(xiàn)在已經(jīng)是司空見慣了。 由于需要存儲的數(shù)據(jù)量不斷增長,開發(fā)者面臨一個問題:應(yīng)該如何擴(kuò)展數(shù)據(jù)庫,分為縱向擴(kuò)展和橫向擴(kuò)展,縱向擴(kuò)展是最省力的做法,但缺點(diǎn)是大型機(jī)一般都非常貴,而且 當(dāng)數(shù)據(jù)量達(dá)到機(jī)器的物理極限時,花再多的錢也買不到更強(qiáng)的機(jī)器了,此時選擇橫向擴(kuò)展更為合適,但橫向擴(kuò)展帶來的另外一個問題就是需要管理的機(jī)器太多。 MongoDB的設(shè)計(jì)采用橫向擴(kuò)展。面向文檔的數(shù)據(jù)模型使它能很容易地在多臺服務(wù)器之間進(jìn)行數(shù)據(jù)分割。MongoDB能夠自動處理跨集群的數(shù)據(jù)和負(fù)載,自動重新分配文檔,以及將 用戶的請求路由到正確的機(jī)器上。這樣,開發(fā)者能夠集中精力編寫應(yīng)用程序,而不需要考慮如何擴(kuò)展的問題。如果一個集群需要更大的容量,只需要向集群添加新服務(wù)器,MongoDB就會自動將現(xiàn)有的數(shù)據(jù)向新服務(wù)器傳送
MongoDB作為一款通用型數(shù)據(jù)庫,除了能夠創(chuàng)建、讀取、更新和刪除數(shù)據(jù)之外,還提供了一系列不斷擴(kuò)展的獨(dú)特功能 #1、索引 支持通用二級索引,允許多種快速查詢,且提供唯一索引、復(fù)合索引、地理空間索引、全文索引 #2、聚合 支持聚合管道,用戶能通過簡單的片段創(chuàng)建復(fù)雜的集合,并通過數(shù)據(jù)庫自動優(yōu)化 #3、特殊的集合類型 支持存在時間有限的集合,適用于那些將在某個時刻過期的數(shù)據(jù),如會話session。類似地,MongoDB也支持固定大小的集合,用于保存近期數(shù)據(jù),如日志 #4、文件存儲 支持一種非常易用的協(xié)議,用于存儲大文件和文件元數(shù)據(jù)。MongoDB并不具備一些在關(guān)系型數(shù)據(jù)庫中很普遍的功能,如鏈接join和復(fù)雜的多行事務(wù)。省略 這些的功能是處于架構(gòu)上的考慮,或者說為了得到更好的擴(kuò)展性,因?yàn)樵诜植际较到y(tǒng)中這兩個功能難以高效地實(shí)現(xiàn)
MongoDB的一個主要目標(biāo)是提供卓越的性能,這很大程度上決定了MongoDB的設(shè)計(jì)。MongoDB把盡可能多的內(nèi)存用作緩存cache,視圖為每次查詢自動選擇正確的索引。 總之各方面的設(shè)計(jì)都旨在保持它的高性能 雖然MongoDB非常強(qiáng)大并試圖保留關(guān)系型數(shù)據(jù)庫的很多特性,但它并不追求具備關(guān)系型數(shù)據(jù)庫的所有功能。只要有可能,數(shù)據(jù)庫服務(wù)器就會將處理邏輯交給客戶端。這種精簡方式的設(shè)計(jì)是MongoDB能夠?qū)崿F(xiàn)如此高性能的原因之一
需要注意的是: #1、文檔中的鍵/值對是有序的。 #2、文檔中的值不僅可以是在雙引號里面的字符串,還可以是其他幾種數(shù)據(jù)類型(甚至可以是整個嵌入的文檔)。 #3、MongoDB區(qū)分類型和大小寫。 #4、MongoDB的文檔不能有重復(fù)的鍵。 #5、文檔中的值可以是多種不同的數(shù)據(jù)類型,也可以是一個完整的內(nèi)嵌文檔。文檔的鍵是字符串。除了少數(shù)例外情況,鍵可以使用任意UTF-8字符。 文檔鍵命名規(guī)范: #1、鍵不能含有\(zhòng)0 (空字符)。這個字符用來表示鍵的結(jié)尾。 #2、.和$有特別的意義,只有在特定環(huán)境下才能使用。 #3、以下劃線"_"開頭的鍵是保留的(不是嚴(yán)格要求的)。
#1、集合存在于數(shù)據(jù)庫中,通常情況下為了方便管理,不同格式和類型的數(shù)據(jù)應(yīng)該插入到不同的集合,但其實(shí)集合沒有固定的結(jié)構(gòu),這意味著我們完全可以把不同格式和類型的數(shù)據(jù)統(tǒng)統(tǒng)插入一個集合中。 #2、組織子集合的方式就是使用“.”,分隔不同命名空間的子集合。 比如一個具有博客功能的應(yīng)用可能包含兩個集合,分別是blog.posts和blog.authors,這是為了使組織結(jié)構(gòu)更清晰,這里的blog集合(這個集合甚至不需要存在)跟它的兩個子集合沒有任何關(guān)系。 在MongoDB中,使用子集合來組織數(shù)據(jù)非常高效,值得推薦 #3、當(dāng)?shù)谝粋€文檔插入時,集合就會被創(chuàng)建。合法的集合名: 集合名不能是空字符串""。 集合名不能含有\(zhòng)0字符(空字符),這個字符表示集合名的結(jié)尾。 集合名不能以"system."開頭,這是為系統(tǒng)集合保留的前綴。 用戶創(chuàng)建的集合名字不能含有保留字符。有些驅(qū)動程序的確支持在集合名里面包含,這是因?yàn)槟承┫到y(tǒng)生成的集合中包含該字符。除非你要訪問這種系統(tǒng)創(chuàng)建的集合,否則千萬不要在名字里出現(xiàn)$。
數(shù)據(jù)庫也通過名字來標(biāo)識。數(shù)據(jù)庫名可以是滿足以下條件的任意UTF-8字符串: #1、不能是空字符串("")。 #2、不得含有' '(空格)、.、$、/、\和\0 (空字符)。 #3、應(yīng)全部小寫。 #4、最多64字節(jié)。 有一些數(shù)據(jù)庫名是保留的,可以直接訪問這些有特殊作用的數(shù)據(jù)庫。 #1、admin: 從身份認(rèn)證的角度講,這是“root”數(shù)據(jù)庫,如果將一個用戶添加到admin數(shù)據(jù)庫,這個用戶將自動獲得所有數(shù)據(jù)庫的權(quán)限。再者,一些特定的服務(wù)器端命令也只能從admin數(shù)據(jù)庫運(yùn)行,如列出所有數(shù)據(jù)庫或關(guān)閉服務(wù)器 #2、local: 這個數(shù)據(jù)庫永遠(yuǎn)都不可以復(fù)制,且一臺服務(wù)器上的所有本地集合都可以存儲在這個數(shù)據(jù)庫中 #3、config: MongoDB用于分片設(shè)置時,分片信息會存儲在config數(shù)據(jù)庫中
例如: 如果要使用cms數(shù)據(jù)庫中的blog.posts集合,這個集合的命名空間就是 cmd.blog.posts。命名空間的長度不得超過121個字節(jié),且在實(shí)際使用中應(yīng)該小于100個字節(jié)
#1、安裝路徑為D:\MongoDB,將D:\MongoDB\bin目錄加入環(huán)境變量#2、新建目錄與文件D:\MongoDB\data\db D:\MongoDB\log\mongod.log#3、新建配置文件mongod.cfg,參考:https://docs.mongodb.com/manual/reference/configuration-options/systemLog: destination: file path: "D:\MongoDB\log\mongod.log" logAppend: true storage: journal: enabled: true dbPath: "D:\MongoDB\data\db"net: bindIp: 0.0.0.0 port: 27017setParameter: enableLocalhostAuthBypass: false #4、制作系統(tǒng)服務(wù)mongod --config "D:\MongoDB\mongod.cfg" --bind_ip 0.0.0.0 --install 或者直接在命令行指定配置 mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install 先停掉服務(wù):net stop MongoDB 然后移除服務(wù):mongo --remove 再重新制作服務(wù),需要加上--auth,表示加載認(rèn)證功能 mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install --auth #5、啟動\關(guān)閉net start MongoDB net stop MongoDB#6、登錄mongo 鏈接:http://www.runoob.com/mongodb/mongodb-window-install.html
#1、創(chuàng)建賬號use admin db.createUser( { user: "root", pwd: "123", roles: [ { role: "root", db: "admin" } ] })use test db.createUser( { user: "tom", pwd: "123", roles: [ { role: "readWrite", db: "test" }, { role: "read", db: "db1" } ] })#2、重啟數(shù)據(jù)庫mongod --remove mongod --config "C:\mongodb\mongod.cfg" --bind_ip 0.0.0.0 --install --auth#3、登錄:注意使用雙引號而非單引號mongo --port 27017 -u "root" -p "123" --authenticationDatabase "admin"也可以在登錄之后用db.auth("賬號","密碼")登錄 mongo use admin db.auth("root","123")#推薦博客:https://www.cnblogs.com/zhoujinyi/p/4610050.html
#1、mongo 127.0.0.1:27017/config #連接到任何數(shù)據(jù)庫config #2、mongo --nodb #不連接到任何數(shù)據(jù)庫 #3、啟動之后,在需要時運(yùn)行new Mongo(hostname)命令就可以連接到想要的mongod了: > conn=new Mongo('127.0.0.1:27017') connection to 127.0.0.1:27017 > db=conn.getDB('admin') admin #4、help查看幫助 #5、mongo時一個簡化的JavaScript shell,是可以執(zhí)行JavaScript腳本的
MongoDB中存儲的文檔必須有一個"_id"鍵。這個鍵的值可以是任意類型,默認(rèn)是個ObjectId對象。 在一個集合里,每個文檔都有唯一的“_id”,確保集合里每個文檔都能被唯一標(biāo)識。 不同集合"_id"的值可以重復(fù),但同一集合內(nèi)"_id"的值必須唯一 #1、ObjectId ObjectId是"_id"的默認(rèn)類型。因?yàn)樵O(shè)計(jì)MongoDb的初衷就是用作分布式數(shù)據(jù)庫,所以能夠在分片環(huán)境中生成 唯一的標(biāo)識符非常重要,而常規(guī)的做法:在多個服務(wù)器上同步自動增加主鍵既費(fèi)時又費(fèi)力,這就是MongoDB采用 ObjectId的原因。 ObjectId采用12字節(jié)的存儲空間,是一個由24個十六進(jìn)制數(shù)字組成的字符串 0|1|2|3| 4|5|6| 7|8 9|10|11 時間戳 機(jī)器 PID 計(jì)數(shù)器 如果快速創(chuàng)建多個ObjectId,會發(fā)現(xiàn)每次只有最后幾位有變化。另外,中間的幾位數(shù)字也會變化(要是在創(chuàng)建過程中停頓幾秒)。 這是ObjectId的創(chuàng)建方式導(dǎo)致的,如上圖 時間戳單位為秒,與隨后5個字節(jié)組合起來,提供了秒級的唯一性。這個4個字節(jié)隱藏了文檔的創(chuàng)建時間,絕大多數(shù)驅(qū)動程序都會提供 一個方法,用于從ObjectId中獲取這些信息。 因?yàn)槭褂玫氖钱?dāng)前時間,很多用戶擔(dān)心要對服務(wù)器進(jìn)行時鐘同步。其實(shí)沒必要,因?yàn)闀r間戳的實(shí)際值并不重要,只要它總是不停增加就好。 接下來3個字節(jié)是所在主機(jī)的唯一標(biāo)識符。通常是機(jī)器主機(jī)名的散列值。這樣就可以保證不同主機(jī)生成不同的ObjectId,不產(chǎn)生沖突 接下來連個字節(jié)確保了在同一臺機(jī)器上并發(fā)的多個進(jìn)程產(chǎn)生的ObjectId是唯一的 前9個字節(jié)確保了同一秒鐘不同機(jī)器不同進(jìn)程產(chǎn)生的ObjectId是唯一的。最后3個字節(jié)是一個自動增加的 計(jì)數(shù)器。確保相同進(jìn)程的同一秒產(chǎn)生的 ObjectId也是不一樣的。 #2、自動生成_id 如果插入文檔時沒有"_id"鍵,系統(tǒng)會自幫你創(chuàng)建 一個??梢杂蒑ongoDb服務(wù)器來做這件事。 但通常會在客戶端由驅(qū)動程序完成。這一做法非常好地體現(xiàn)了MongoDb的哲學(xué):能交給客戶端驅(qū)動程序來做的事情就不要交給服務(wù)器來做。 這種理念背后的原因是:即便是像MongoDB這樣擴(kuò)展性非常好的數(shù)據(jù)庫,擴(kuò)展應(yīng)用層也要比擴(kuò)展數(shù)據(jù)庫層容易的多。將工作交給客戶端做就 減輕了數(shù)據(jù)庫擴(kuò)展的負(fù)擔(dān)。
#1、null:用于表示空或不存在的字段d={'x':null}#2、布爾型:true和falsed={'x':true,'y':false}#3、數(shù)值d={'x':3,'y':3.1415926}#4、字符串d={'x':'tom'}#5、日期d={'x':new Date()}d.x.getHours()#6、正則表達(dá)式d={'pattern':/^egon.*?nb$/i}正則寫在//內(nèi),后面的i代表:i 忽略大小寫 m 多行匹配模式 x 忽略非轉(zhuǎn)義的空白字符 s 單行匹配模式#7、數(shù)組d={'x':[1,'a','v']}#8、內(nèi)嵌文檔user={'name':'tom','addr':{'country':'China','city':'YT'}}user.addr.country#9、對象id:是一個12字節(jié)的ID,是文檔的唯一標(biāo)識,不可變d={'x':ObjectId()}
#1、增use db1 #如果數(shù)據(jù)庫不存在,則創(chuàng)建數(shù)據(jù)庫,否則切換到指定數(shù)據(jù)庫。#2、查show dbs #查看所有可以看到,我們剛創(chuàng)建的數(shù)據(jù)庫db1并不在數(shù)據(jù)庫的列表中, 要顯示它,我們需要向db1數(shù)據(jù)庫插入一些數(shù)據(jù)。 db.table1.insert({'a':1})#3、刪use db1 #先切換到要刪的庫下db.dropDatabase() #刪除當(dāng)前庫
#1、增當(dāng)?shù)谝粋€文檔插入時,集合就會被創(chuàng)建> use database1 switched to db database1> db.table1.insert({'a':1})WriteResult({ "nInserted" : 1 })> db.table2.insert({'b':2})WriteResult({ "nInserted" : 1 })db.user db.user.info 表名是user.info,跟user表沒有任何關(guān)系 db.user.auth#2、查> show tables table1 table2#3、刪> db.table1.drop()true> show tables table2
#1、沒有指定_id則默認(rèn)ObjectId,_id不能重復(fù),且在插入后不可變#2、插入單條user0={ "name":"tom", "age":10, 'hobbies':['music','read','dancing'], 'addr':{ 'country':'China', 'city':'BJ' }}db.test.insert(user0)db.test.find()#3、插入多條user1={ "_id":1, "name":"zhang3", "age":10, 'hobbies':['music','read','dancing'], 'addr':{ 'country':'China', 'city':'weifang' }}user2={ "_id":2, "name":"li4", "age":20, 'hobbies':['music','read','run'], 'addr':{ 'country':'China', 'city':'hebei' }}user3={ "_id":3, "name":"wang5", "age":30, 'hobbies':['music','drink'], 'addr':{ 'country':'China', 'city':'heibei' }}user4={ "_id":4, "name":"zhao6", "age":40, 'hobbies':['music','read','dancing','tea'], 'addr':{ 'country':'China', 'city':'BJ' }}user5={ "_id":5, "name":"sun7", "age":50, 'hobbies':['music','read',], 'addr':{ 'country':'China', 'city':'henan' }}db.user.insertMany([user1,user2,user3,user4,user5])db.t1.insert({"_id":1,"a":"1","b":"2","c":"3"})db.t1.save({"_id":1,"z":"6"}) 有就用新的記錄覆蓋掉原來的記錄,無就新增
# SQL:=,!=,>,<,>=,<=# MongoDB:{key:value}代表什么等于什么"$ne"====>不等于"$gt"====>大于"$lt"====>小于"gte"====>大于等于"lte"====>小于等于 其中"$ne"能用于所有數(shù)據(jù)類型#1、select * from db1.user where name = "alex";db.user.find({'name':'alex'})#2、select * from db1.user where name != "alex";db.user.find({'name':{"$ne":'alex'}})#3、select * from db1.user where id > 2;db.user.find({'_id':{'$gt':2}})#4、select * from db1.user where id < 3;db.user.find({'_id':{'$lt':3}})#5、select * from db1.user where id >= 2;db.user.find({"_id":{"$gte":2,}})#6、select * from db1.user where id <= 2;db.user.find({"_id":{"$lte":2}})
# SQL:and,or,not# MongoDB:字典中逗號分隔的多個條件是and關(guān)系,"$or"的條件放到[]內(nèi),"$not"#1、select * from db1.user where id >= 2 and id < 4;db.user.find({'_id':{"$gte":2,"$lt":4}})#2、select * from db1.user where id >= 2 and age < 40;db.user.find({"_id":{"$gte":2},"age":{"$lt":40}})#3、select * from db1.user where id >= 5 or name = "alex";db.user.find({ "$or":[ {'_id':{"$gte":5}}, {"name":"alex"} ]})#4、select * from db1.user where id % 2=1;db.user.find({'_id':{"$mod":[2,1]}})#5、上題,取反db.user.find({'_id':{"$not":{"$mod":[2,1]}}})
# SQL:in,not in# MongoDB:"$in","$nin"#1、select * from db1.user where age in (20,30,31);db.user.find({"age":{"$in":[20,30,31]}})#2、select * from db1.user where name not in ('alex','yuanhao');db.user.find({"name":{"$nin":['alex','yuanhao']}})
# SQL: regexp 正則# MongoDB: /正則表達(dá)/i#1、select * from db1.user where name regexp '^j.*?(g|n)$';db.user.find({'name':/^j.*?(g|n)$/i})
#1、select name,age from db1.user where id=3;db.user.find({'_id':3},{'_id':0,'name':1,'age':1})1:代表要,類似True0:代表不要,類似Flase,默認(rèn)是0
#1、查看有dancing愛好的人db.user.find({'hobbies':'dancing'})#2、查看既有dancing愛好又有tea愛好的人db.user.find({ 'hobbies':{ "$all":['dancing','tea'] }})#3、查看第4個愛好為tea的人:".方法"db.user.find({"hobbies.3":'tea'})#4、查看所有人最后兩個愛好:"$slice"db.user.find({},{'hobbies':{"$slice":-2},"age":0,"_id":0,"name":0,"addr":0})#5、查看所有人的第2個到第3個愛好db.user.find({},{'hobbies':{"$slice":[1,2]},"age":0,"_id":0,"name":0,"addr":0})> db.blog.find().pretty(){ "_id" : 1, "name" : "sun7公司破產(chǎn)的真相", "comments" : [ { "name" : "zhang3", "content" : "sun7是誰???", "thumb" : 200 }, { "name" : "li4", "content" : "我去,真的假的", "thumb" : 300 }, { "name" : "wang5", "content" : "吃喝嫖賭抽,欠下兩個億", "thumb" : 40 }, { "name" : "zhao6", "content" : "丐幫歡迎你", "thumb" : 0 } ]}db.blog.find({},{'comments':{"$slice":-2}}).pretty() #查詢最后兩個db.blog.find({},{'comments':{"$slice":[1,2]}}).pretty() #查詢1到2
# 排序:1代表升序,-1代表降序db.user.find().sort({"name":1})db.user.find().sort({"age":-1,'_id':1})
# 分頁:limit代表取多少個document,skip代表跳過前多少個document。 db.user.find().sort({'age':1}).limit(1).skip(2)
# 獲取數(shù)量db.user.count({'age':{"$gt":30}}) --或者 db.user.find({'age':{"$gt":30}}).count()
#1、{'key':null} 匹配key的值為null或者沒有這個keydb.t2.insert({'a':10,'b':111})db.t2.insert({'a':20})db.t2.insert({'b':null})> db.t2.find({"b":null}){ "_id" : ObjectId("5a5cc2a7c1b4645aad959e5a"), "a" : 20 }{ "_id" : ObjectId("5a5cc2a8c1b4645aad959e5b"), "b" : null }#2、查找所有db.user.find() #等同于db.user.find({})db.user.find().pretty()#3、查找一個,與find用法一致,只是只取匹配成功的第一個db.user.findOne({"_id":{"$gt":3}})#4、去重db.user.find().distinct()
update() 方法用于更新已存在的文檔。語法格式如下: db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> })參數(shù)說明:對比update db1.t1 set name='zhangsan',sex='Male' where name='zhang3' and age=18;query : 相當(dāng)于where條件。 update : update的對象和一些更新的操作符(如$,$inc...等,相當(dāng)于set后面的 upsert : 可選,默認(rèn)為false,代表如果不存在update的記錄不更新也不插入,設(shè)置為true代表插入。 multi : 可選,默認(rèn)為false,代表只更新找到的第一條記錄,設(shè)為true,代表更新找到的全部記錄。 writeConcern :可選,拋出異常的級別。 更新操作是不可分割的:若兩個更新同時發(fā)送,先到達(dá)服務(wù)器的先執(zhí)行,然后執(zhí)行另外一個,不會破壞文檔。
#注意:除非是刪除,否則_id是始終不會變的#1、覆蓋式:db.user.update({'age':20},{"name":"wang5","hobbies_count":3})是用{"_id":2,"name":"wang5","hobbies_count":3}覆蓋原來的記錄#2、一種最簡單的更新就是用一個新的文檔完全替換匹配的文檔。這適用于大規(guī)模式遷移的情況。例如var obj=db.user.findOne({"_id":2})obj.username=obj.name+'SB'obj.hobbies_count++delete obj.age db.user.update({"_id":2},obj)
#設(shè)置:$set通常文檔只會有一部分需要更新。可以使用原子性的更新修改器,指定對文檔中的某些字段進(jìn)行更新。 更新修改器是種特殊的鍵,用來指定復(fù)雜的更新操作,比如修改、增加后者刪除#1、update db1.user set name="wang5" where id = 2db.user.update({'_id':2},{"$set":{"name":"wang5",}})#2、沒有匹配成功則新增一條{"upsert":true}db.user.update({'_id':6},{"$set":{"name":"wang5","age":18}},{"upsert":true})#3、默認(rèn)只改匹配成功的第一條,{"multi":改多條}db.user.update({'_id':{"$gt":4}},{"$set":{"age":28}})db.user.update({'_id':{"$gt":4}},{"$set":{"age":38}},{"multi":true})#4、修改內(nèi)嵌文檔,把名字為wang5的人所在的地址國家改成Japandb.user.update({'name':"wang5"},{"$set":{"addr.country":"Japan"}})#5、把名字為wang5的人的地2個愛好改成piaodb.user.update({'name':"wang5"},{"$set":{"hobbies.1":"piao"}})#6、刪除wang5的愛好,$unsetdb.user.update({'name':"wang5"},{"$unset":{"hobbies":""}})
#增加和減少:$inc#1、所有人年齡增加一歲db.user.update({}, { "$inc":{"age":1} }, { "multi":true } )#2、所有人年齡減少5歲db.user.update({}, { "$inc":{"age":-5} }, { "multi":true } )
#添加刪除數(shù)組內(nèi)元素 往數(shù)組內(nèi)添加元素:$push#1、為名字為wang5的人添加一個愛好readdb.user.update({"name":"wang5"},{"$push":{"hobbies":"read"}})#2、為名字為wang5的人一次添加多個愛好tea,dancingdb.user.update({"name":"wang5"},{"$push":{ "hobbies":{"$each":["tea","dancing"]}}})按照位置且只能從開頭或結(jié)尾刪除元素:$pop#3、{"$pop":{"key":1}} 從數(shù)組末尾刪除一個元素db.user.update({"name":"wang5"},{"$pop":{ "hobbies":1}})#4、{"$pop":{"key":-1}} 從頭部刪除db.user.update({"name":"wang5"},{"$pop":{ "hobbies":-1}})#5、按照條件刪除元素,:"$pull" 把符合條件的統(tǒng)統(tǒng)刪掉,而$pop只能從兩端刪db.user.update({'addr.country':"China"},{"$pull":{ "hobbies":"read"}},{ "multi":true})
#避免添加重復(fù):"$addToSet"db.urls.insert({"_id":1,"urls":[]})db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})db.urls.update({"_id":1},{ "$addToSet":{ "urls":{ "$each":[ 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.xxxx.com' ] } } })
#1、了解:限制大小"$slice",只留最后n個db.user.update({"_id":5},{ "$push":{"hobbies":{ "$each":["read",'music','dancing'], "$slice":-2 } }})#2、了解:排序The $sort element value must be either 1 or -1"db.user.update({"_id":5},{ "$push":{"hobbies":{ "$each":["read",'music','dancing'], "$slice":-1, "$sort":-1 } }})#注意:不能只將"$slice"或者"$sort"與"$push"配合使用,且必須使用"$eah"
#1、刪除多個中的第一個db.user.deleteOne({ 'age': 8 })#2、刪除國家為China的全部db.user.deleteMany( {'addr.country': 'China'} ) #3、刪除全部db.user.deleteMany({})
如果你有數(shù)據(jù)存儲在MongoDB中,你想做的可能就不僅僅是將數(shù)據(jù)提取出來那么簡單了;你可能希望對數(shù)據(jù)進(jìn)行分析并加以利用。MongoDB提供了以下聚合工具:#1、聚合框架#2、MapReduce(詳見MongoDB權(quán)威指南)#3、幾個簡單聚合命令:count、distinct和group。(詳見MongoDB權(quán)威指南)#聚合框架:可以使用多個構(gòu)件創(chuàng)建一個管道,上一個構(gòu)件的結(jié)果傳給下一個構(gòu)件。 這些構(gòu)件包括(括號內(nèi)為構(gòu)件對應(yīng)的操作符):篩選($match)、投射($project)、分組($group)、排序($sort)、限制($limit)、跳過($skip)不同的管道操作符可以任意組合,重復(fù)使用
from pymongo import MongoClientimport datetime client=MongoClient('mongodb://root:123@localhost:27017')table=client['db1']['emp']# table.drop()l=[('tom','male',18,'20170301','校長',73000.33,401,1), #以下是教學(xué)部('bob','male',78,'20150302','teacher',10000.31,401,1),('sam','male',81,'20130305','teacher',8300,401,1),('zhang3','male',73,'20140701','teacher',3500,401,1),('li4','male',28,'20121101','teacher',2100,401,1),('may','female',18,'20110211','teacher',9000,401,1),('wang5','male',18,'19000301','teacher',30000,401,1),('成龍','male',48,'20101111','teacher',10000,401,1),('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是銷售部門('丫丫','female',38,'20101101','sale',2000.35,402,2),('丁丁','female',18,'20110312','sale',1000.37,402,2),('星星','female',18,'20160513','sale',3000.29,402,2),('格格','female',28,'20170127','sale',4000.33,402,2),('張野','male',28,'20160311','operation',10000.13,403,3), #以下是運(yùn)營部門('程咬金','male',18,'19970312','operation',20000,403,3),('程咬銀','female',18,'20130311','operation',19000,403,3),('程咬銅','male',18,'20150411','operation',18000,403,3),('程咬鐵','female',18,'20140512','operation',17000,403,3)]for n,item in enumerate(l): d={ "_id":n, 'name':item[0], 'sex':item[1], 'age':item[2], 'hire_date':datetime.datetime.strptime(item[3],'%Y%m%d'), 'post':item[4], 'salary':item[5] } table.save(d)
{"$match":{"字段":"條件"}},可以使用任何常用查詢操作符$gt,$lt,$in等#例1、select * from db1.emp where post='teacher';db.emp.aggregate({"$match":{"post":"teacher"}})#例2、select * from db1.emp where id > 3 group by post; db.emp.aggregate( {"$match":{"_id":{"$gt":3}}}, {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}})#例3、select * from db1.emp where id > 3 group by post having avg(salary) > 10000; db.emp.aggregate( {"$match":{"_id":{"$gt":3}}}, {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}}, {"$match":{"avg_salary":{"$gt":10000}}})
{"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表達(dá)式"}}#1、select name,post,(age+1) as new_age from db1.emp;db.emp.aggregate( {"$project":{ "name":1, "post":1, "new_age":{"$add":["$age",1]} }})#2、表達(dá)式之?dāng)?shù)學(xué)表達(dá)式{"$add":[expr1,expr2,...,exprN]} #相加{"$subtract":[expr1,expr2]} #第一個減第二個{"$multiply":[expr1,expr2,...,exprN]} #相乘{(lán)"$pide":[expr1,expr2]} #第一個表達(dá)式除以第二個表達(dá)式的商作為結(jié)果{"$mod":[expr1,expr2]} #第一個表達(dá)式除以第二個表達(dá)式得到的余數(shù)作為結(jié)果#3、表達(dá)式之日期表達(dá)式:$year,$month,$week,$dayOfMonth,$dayOfWeek,$dayOfYear,$hour,$minute,$second#例如:select name,date_format("%Y") as hire_year from db1.empdb.emp.aggregate( {"$project":{"name":1,"hire_year":{"$year":"$hire_date"}}})#例如查看每個員工的工作多長時間db.emp.aggregate( {"$project":{"name":1,"hire_period":{ "$subtract":[ {"$year":new Date()}, {"$year":"$hire_date"} ] }}})#4、字符串表達(dá)式{"$substr":[字符串/$值為字符串的字段名,起始位置,截取幾個字節(jié)]}{"$concat":[expr1,expr2,...,exprN]} #指定的表達(dá)式或字符串連接在一起返回,只支持字符串拼接{"$toLower":expr}{"$toUpper":expr}db.emp.aggregate( {"$project":{"NAME":{"$toUpper":"$name"}}})#5、邏輯表達(dá)式$and$or$not其他見Mongodb權(quán)威指南
{"$group":{"_id":分組字段,"新的字段名":聚合操作符}}#1、將分組字段傳給$group函數(shù)的_id字段即可{"$group":{"_id":"$sex"}} #按照性別分組{"$group":{"_id":"$post"}} #按照職位分組{"$group":{"_id":{"state":"$state","city":"$city"}}} #按照多個字段分組,比如按照州市分組#2、分組后聚合得結(jié)果,類似于sql中聚合函數(shù)的聚合操作符:$sum、$avg、$max、$min、$first、$last#例1:select post,max(salary) from db1.emp group by post; db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}})#例2:去每個部門最大薪資與最低薪資db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}})#例3:如果字段是排序后的,那么$first,$last會很有用,比用$max和$min效率高db.emp.aggregate({"$group":{"_id":"$post","first_id":{"$first":"$_id"}}})#例4:求每個部門的總工資db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":"$salary"}}})#例5:求每個部門的人數(shù)db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":1}}})#3、數(shù)組操作符{"$addToSet":expr}:不重復(fù){"$push":expr}:重復(fù)#例:查詢崗位名以及各崗位內(nèi)的員工姓名:select post,group_concat(name) from db1.emp group by post;db.emp.aggregate({"$group":{"_id":"$post","names":{"$push":"$name"}}})db.emp.aggregate({"$group":{"_id":"$post","names":{"$addToSet":"$name"}}})
{"$sort":{"字段名":1,"字段名":-1}} #1升序,-1降序{"$limit":n} {"$skip":n} #跳過多少個文檔#例1、取平均工資最高的前兩個部門db.emp.aggregate({ "$group":{"_id":"$post","平均工資":{"$avg":"$salary"}}},{ "$sort":{"平均工資":-1}},{ "$limit":2})#例2、db.emp.aggregate({ "$group":{"_id":"$post","平均工資":{"$avg":"$salary"}}},{ "$sort":{"平均工資":-1}},{ "$limit":2},{ "$skip":1})
#集合users包含的文檔如下{ "_id" : 1, "name" : "dave123", "q1" : true, "q2" : true }{ "_id" : 2, "name" : "dave2", "q1" : false, "q2" : false }{ "_id" : 3, "name" : "ahn", "q1" : true, "q2" : true }{ "_id" : 4, "name" : "li", "q1" : true, "q2" : false }{ "_id" : 5, "name" : "annT", "q1" : false, "q2" : true }{ "_id" : 6, "name" : "li", "q1" : true, "q2" : true }{ "_id" : 7, "name" : "ty", "q1" : false, "q2" : true }#下述操作時從users集合中隨機(jī)選取3個文檔db.users.aggregate( [ { $sample: { size: 3 } } ])
MongoDB是一款強(qiáng)大、靈活、且易于擴(kuò)展的通用型數(shù)據(jù)庫。
MongoDB是一個面向文檔(document-oriented)的數(shù)據(jù)庫,而不是關(guān)系型數(shù)據(jù)庫。 不采用關(guān)系型主要是為了獲得更好得擴(kuò)展性。當(dāng)然還有一些其他好處,與關(guān)系數(shù)據(jù)庫相比,面向文檔的數(shù)據(jù)庫不再有“行“(row)的概念取而代之的是更為靈活的“文檔”(document)模型。 通過在文檔中嵌入文檔和數(shù)組,面向文檔的方法能夠僅使用一條記錄來表現(xiàn)復(fù)雜的層級關(guān)系,這與現(xiàn)代的面向?qū)ο笳Z言的開發(fā)者對數(shù)據(jù)的看法一致。 另外,不再有預(yù)定義模式(predefined schema):文檔的鍵(key)和值(value)不再是固定的類型和大小。由于沒有固定的模式,根據(jù)需要添加或刪除字段變得更容易了。通常由于開發(fā)者能夠進(jìn)行快速迭代,所以開發(fā)進(jìn)程得以加快。而且,實(shí)驗(yàn)更容易進(jìn)行。開發(fā)者能嘗試大量的數(shù)據(jù)模型,從中選一個最好的。
應(yīng)用程序數(shù)據(jù)集的大小正在以不可思議的速度增長。隨著可用帶寬的增長和存儲器價格的下降,即使是一個小規(guī)模的應(yīng)用程序,需要存儲的數(shù)據(jù)量也可能大的驚人,甚至超出 了很多數(shù)據(jù)庫的處理能力。過去非常罕見的T級數(shù)據(jù),現(xiàn)在已經(jīng)是司空見慣了。 由于需要存儲的數(shù)據(jù)量不斷增長,開發(fā)者面臨一個問題:應(yīng)該如何擴(kuò)展數(shù)據(jù)庫,分為縱向擴(kuò)展和橫向擴(kuò)展,縱向擴(kuò)展是最省力的做法,但缺點(diǎn)是大型機(jī)一般都非常貴,而且 當(dāng)數(shù)據(jù)量達(dá)到機(jī)器的物理極限時,花再多的錢也買不到更強(qiáng)的機(jī)器了,此時選擇橫向擴(kuò)展更為合適,但橫向擴(kuò)展帶來的另外一個問題就是需要管理的機(jī)器太多。 MongoDB的設(shè)計(jì)采用橫向擴(kuò)展。面向文檔的數(shù)據(jù)模型使它能很容易地在多臺服務(wù)器之間進(jìn)行數(shù)據(jù)分割。MongoDB能夠自動處理跨集群的數(shù)據(jù)和負(fù)載,自動重新分配文檔,以及將 用戶的請求路由到正確的機(jī)器上。這樣,開發(fā)者能夠集中精力編寫應(yīng)用程序,而不需要考慮如何擴(kuò)展的問題。如果一個集群需要更大的容量,只需要向集群添加新服務(wù)器,MongoDB就會自動將現(xiàn)有的數(shù)據(jù)向新服務(wù)器傳送
MongoDB作為一款通用型數(shù)據(jù)庫,除了能夠創(chuàng)建、讀取、更新和刪除數(shù)據(jù)之外,還提供了一系列不斷擴(kuò)展的獨(dú)特功能 #1、索引 支持通用二級索引,允許多種快速查詢,且提供唯一索引、復(fù)合索引、地理空間索引、全文索引 #2、聚合 支持聚合管道,用戶能通過簡單的片段創(chuàng)建復(fù)雜的集合,并通過數(shù)據(jù)庫自動優(yōu)化 #3、特殊的集合類型 支持存在時間有限的集合,適用于那些將在某個時刻過期的數(shù)據(jù),如會話session。類似地,MongoDB也支持固定大小的集合,用于保存近期數(shù)據(jù),如日志 #4、文件存儲 支持一種非常易用的協(xié)議,用于存儲大文件和文件元數(shù)據(jù)。MongoDB并不具備一些在關(guān)系型數(shù)據(jù)庫中很普遍的功能,如鏈接join和復(fù)雜的多行事務(wù)。省略 這些的功能是處于架構(gòu)上的考慮,或者說為了得到更好的擴(kuò)展性,因?yàn)樵诜植际较到y(tǒng)中這兩個功能難以高效地實(shí)現(xiàn)
MongoDB的一個主要目標(biāo)是提供卓越的性能,這很大程度上決定了MongoDB的設(shè)計(jì)。MongoDB把盡可能多的內(nèi)存用作緩存cache,視圖為每次查詢自動選擇正確的索引。 總之各方面的設(shè)計(jì)都旨在保持它的高性能 雖然MongoDB非常強(qiáng)大并試圖保留關(guān)系型數(shù)據(jù)庫的很多特性,但它并不追求具備關(guān)系型數(shù)據(jù)庫的所有功能。只要有可能,數(shù)據(jù)庫服務(wù)器就會將處理邏輯交給客戶端。這種精簡方式的設(shè)計(jì)是MongoDB能夠?qū)崿F(xiàn)如此高性能的原因之一
需要注意的是: #1、文檔中的鍵/值對是有序的。 #2、文檔中的值不僅可以是在雙引號里面的字符串,還可以是其他幾種數(shù)據(jù)類型(甚至可以是整個嵌入的文檔)。 #3、MongoDB區(qū)分類型和大小寫。 #4、MongoDB的文檔不能有重復(fù)的鍵。 #5、文檔中的值可以是多種不同的數(shù)據(jù)類型,也可以是一個完整的內(nèi)嵌文檔。文檔的鍵是字符串。除了少數(shù)例外情況,鍵可以使用任意UTF-8字符。 文檔鍵命名規(guī)范: #1、鍵不能含有\(zhòng)0 (空字符)。這個字符用來表示鍵的結(jié)尾。 #2、.和$有特別的意義,只有在特定環(huán)境下才能使用。 #3、以下劃線"_"開頭的鍵是保留的(不是嚴(yán)格要求的)。
#1、集合存在于數(shù)據(jù)庫中,通常情況下為了方便管理,不同格式和類型的數(shù)據(jù)應(yīng)該插入到不同的集合,但其實(shí)集合沒有固定的結(jié)構(gòu),這意味著我們完全可以把不同格式和類型的數(shù)據(jù)統(tǒng)統(tǒng)插入一個集合中。 #2、組織子集合的方式就是使用“.”,分隔不同命名空間的子集合。 比如一個具有博客功能的應(yīng)用可能包含兩個集合,分別是blog.posts和blog.authors,這是為了使組織結(jié)構(gòu)更清晰,這里的blog集合(這個集合甚至不需要存在)跟它的兩個子集合沒有任何關(guān)系。 在MongoDB中,使用子集合來組織數(shù)據(jù)非常高效,值得推薦 #3、當(dāng)?shù)谝粋€文檔插入時,集合就會被創(chuàng)建。合法的集合名: 集合名不能是空字符串""。 集合名不能含有\(zhòng)0字符(空字符),這個字符表示集合名的結(jié)尾。 集合名不能以"system."開頭,這是為系統(tǒng)集合保留的前綴。 用戶創(chuàng)建的集合名字不能含有保留字符。有些驅(qū)動程序的確支持在集合名里面包含,這是因?yàn)槟承┫到y(tǒng)生成的集合中包含該字符。除非你要訪問這種系統(tǒng)創(chuàng)建的集合,否則千萬不要在名字里出現(xiàn)$。
數(shù)據(jù)庫也通過名字來標(biāo)識。數(shù)據(jù)庫名可以是滿足以下條件的任意UTF-8字符串: #1、不能是空字符串("")。 #2、不得含有' '(空格)、.、$、/、\和\0 (空字符)。 #3、應(yīng)全部小寫。 #4、最多64字節(jié)。 有一些數(shù)據(jù)庫名是保留的,可以直接訪問這些有特殊作用的數(shù)據(jù)庫。 #1、admin: 從身份認(rèn)證的角度講,這是“root”數(shù)據(jù)庫,如果將一個用戶添加到admin數(shù)據(jù)庫,這個用戶將自動獲得所有數(shù)據(jù)庫的權(quán)限。再者,一些特定的服務(wù)器端命令也只能從admin數(shù)據(jù)庫運(yùn)行,如列出所有數(shù)據(jù)庫或關(guān)閉服務(wù)器 #2、local: 這個數(shù)據(jù)庫永遠(yuǎn)都不可以復(fù)制,且一臺服務(wù)器上的所有本地集合都可以存儲在這個數(shù)據(jù)庫中 #3、config: MongoDB用于分片設(shè)置時,分片信息會存儲在config數(shù)據(jù)庫中
例如: 如果要使用cms數(shù)據(jù)庫中的blog.posts集合,這個集合的命名空間就是 cmd.blog.posts。命名空間的長度不得超過121個字節(jié),且在實(shí)際使用中應(yīng)該小于100個字節(jié)
#1、安裝路徑為D:\MongoDB,將D:\MongoDB\bin目錄加入環(huán)境變量#2、新建目錄與文件D:\MongoDB\data\db D:\MongoDB\log\mongod.log#3、新建配置文件mongod.cfg,參考:https://docs.mongodb.com/manual/reference/configuration-options/systemLog: destination: file path: "D:\MongoDB\log\mongod.log" logAppend: true storage: journal: enabled: true dbPath: "D:\MongoDB\data\db"net: bindIp: 0.0.0.0 port: 27017setParameter: enableLocalhostAuthBypass: false #4、制作系統(tǒng)服務(wù)mongod --config "D:\MongoDB\mongod.cfg" --bind_ip 0.0.0.0 --install 或者直接在命令行指定配置 mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install 先停掉服務(wù):net stop MongoDB 然后移除服務(wù):mongo --remove 再重新制作服務(wù),需要加上--auth,表示加載認(rèn)證功能 mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install --auth #5、啟動\關(guān)閉net start MongoDB net stop MongoDB#6、登錄mongo 鏈接:http://www.runoob.com/mongodb/mongodb-window-install.html
#1、創(chuàng)建賬號use admin db.createUser( { user: "root", pwd: "123", roles: [ { role: "root", db: "admin" } ] })use test db.createUser( { user: "tom", pwd: "123", roles: [ { role: "readWrite", db: "test" }, { role: "read", db: "db1" } ] })#2、重啟數(shù)據(jù)庫mongod --remove mongod --config "C:\mongodb\mongod.cfg" --bind_ip 0.0.0.0 --install --auth#3、登錄:注意使用雙引號而非單引號mongo --port 27017 -u "root" -p "123" --authenticationDatabase "admin"也可以在登錄之后用db.auth("賬號","密碼")登錄 mongo use admin db.auth("root","123")#推薦博客:https://www.cnblogs.com/zhoujinyi/p/4610050.html
#1、mongo 127.0.0.1:27017/config #連接到任何數(shù)據(jù)庫config #2、mongo --nodb #不連接到任何數(shù)據(jù)庫 #3、啟動之后,在需要時運(yùn)行new Mongo(hostname)命令就可以連接到想要的mongod了: > conn=new Mongo('127.0.0.1:27017') connection to 127.0.0.1:27017 > db=conn.getDB('admin') admin #4、help查看幫助 #5、mongo時一個簡化的JavaScript shell,是可以執(zhí)行JavaScript腳本的
MongoDB中存儲的文檔必須有一個"_id"鍵。這個鍵的值可以是任意類型,默認(rèn)是個ObjectId對象。 在一個集合里,每個文檔都有唯一的“_id”,確保集合里每個文檔都能被唯一標(biāo)識。 不同集合"_id"的值可以重復(fù),但同一集合內(nèi)"_id"的值必須唯一 #1、ObjectId ObjectId是"_id"的默認(rèn)類型。因?yàn)樵O(shè)計(jì)MongoDb的初衷就是用作分布式數(shù)據(jù)庫,所以能夠在分片環(huán)境中生成 唯一的標(biāo)識符非常重要,而常規(guī)的做法:在多個服務(wù)器上同步自動增加主鍵既費(fèi)時又費(fèi)力,這就是MongoDB采用 ObjectId的原因。 ObjectId采用12字節(jié)的存儲空間,是一個由24個十六進(jìn)制數(shù)字組成的字符串 0|1|2|3| 4|5|6| 7|8 9|10|11 時間戳 機(jī)器 PID 計(jì)數(shù)器 如果快速創(chuàng)建多個ObjectId,會發(fā)現(xiàn)每次只有最后幾位有變化。另外,中間的幾位數(shù)字也會變化(要是在創(chuàng)建過程中停頓幾秒)。 這是ObjectId的創(chuàng)建方式導(dǎo)致的,如上圖 時間戳單位為秒,與隨后5個字節(jié)組合起來,提供了秒級的唯一性。這個4個字節(jié)隱藏了文檔的創(chuàng)建時間,絕大多數(shù)驅(qū)動程序都會提供 一個方法,用于從ObjectId中獲取這些信息。 因?yàn)槭褂玫氖钱?dāng)前時間,很多用戶擔(dān)心要對服務(wù)器進(jìn)行時鐘同步。其實(shí)沒必要,因?yàn)闀r間戳的實(shí)際值并不重要,只要它總是不停增加就好。 接下來3個字節(jié)是所在主機(jī)的唯一標(biāo)識符。通常是機(jī)器主機(jī)名的散列值。這樣就可以保證不同主機(jī)生成不同的ObjectId,不產(chǎn)生沖突 接下來連個字節(jié)確保了在同一臺機(jī)器上并發(fā)的多個進(jìn)程產(chǎn)生的ObjectId是唯一的 前9個字節(jié)確保了同一秒鐘不同機(jī)器不同進(jìn)程產(chǎn)生的ObjectId是唯一的。最后3個字節(jié)是一個自動增加的 計(jì)數(shù)器。確保相同進(jìn)程的同一秒產(chǎn)生的 ObjectId也是不一樣的。 #2、自動生成_id 如果插入文檔時沒有"_id"鍵,系統(tǒng)會自幫你創(chuàng)建 一個??梢杂蒑ongoDb服務(wù)器來做這件事。 但通常會在客戶端由驅(qū)動程序完成。這一做法非常好地體現(xiàn)了MongoDb的哲學(xué):能交給客戶端驅(qū)動程序來做的事情就不要交給服務(wù)器來做。 這種理念背后的原因是:即便是像MongoDB這樣擴(kuò)展性非常好的數(shù)據(jù)庫,擴(kuò)展應(yīng)用層也要比擴(kuò)展數(shù)據(jù)庫層容易的多。將工作交給客戶端做就 減輕了數(shù)據(jù)庫擴(kuò)展的負(fù)擔(dān)。
#1、null:用于表示空或不存在的字段d={'x':null}#2、布爾型:true和falsed={'x':true,'y':false}#3、數(shù)值d={'x':3,'y':3.1415926}#4、字符串d={'x':'tom'}#5、日期d={'x':new Date()}d.x.getHours()#6、正則表達(dá)式d={'pattern':/^egon.*?nb$/i}正則寫在//內(nèi),后面的i代表:i 忽略大小寫 m 多行匹配模式 x 忽略非轉(zhuǎn)義的空白字符 s 單行匹配模式#7、數(shù)組d={'x':[1,'a','v']}#8、內(nèi)嵌文檔user={'name':'tom','addr':{'country':'China','city':'YT'}}user.addr.country#9、對象id:是一個12字節(jié)的ID,是文檔的唯一標(biāo)識,不可變d={'x':ObjectId()}
#1、增use db1 #如果數(shù)據(jù)庫不存在,則創(chuàng)建數(shù)據(jù)庫,否則切換到指定數(shù)據(jù)庫。#2、查show dbs #查看所有可以看到,我們剛創(chuàng)建的數(shù)據(jù)庫db1并不在數(shù)據(jù)庫的列表中, 要顯示它,我們需要向db1數(shù)據(jù)庫插入一些數(shù)據(jù)。 db.table1.insert({'a':1})#3、刪use db1 #先切換到要刪的庫下db.dropDatabase() #刪除當(dāng)前庫
#1、增當(dāng)?shù)谝粋€文檔插入時,集合就會被創(chuàng)建> use database1 switched to db database1> db.table1.insert({'a':1})WriteResult({ "nInserted" : 1 })> db.table2.insert({'b':2})WriteResult({ "nInserted" : 1 })db.user db.user.info 表名是user.info,跟user表沒有任何關(guān)系 db.user.auth#2、查> show tables table1 table2#3、刪> db.table1.drop()true> show tables table2
#1、沒有指定_id則默認(rèn)ObjectId,_id不能重復(fù),且在插入后不可變#2、插入單條user0={ "name":"tom", "age":10, 'hobbies':['music','read','dancing'], 'addr':{ 'country':'China', 'city':'BJ' }}db.test.insert(user0)db.test.find()#3、插入多條user1={ "_id":1, "name":"zhang3", "age":10, 'hobbies':['music','read','dancing'], 'addr':{ 'country':'China', 'city':'weifang' }}user2={ "_id":2, "name":"li4", "age":20, 'hobbies':['music','read','run'], 'addr':{ 'country':'China', 'city':'hebei' }}user3={ "_id":3, "name":"wang5", "age":30, 'hobbies':['music','drink'], 'addr':{ 'country':'China', 'city':'heibei' }}user4={ "_id":4, "name":"zhao6", "age":40, 'hobbies':['music','read','dancing','tea'], 'addr':{ 'country':'China', 'city':'BJ' }}user5={ "_id":5, "name":"sun7", "age":50, 'hobbies':['music','read',], 'addr':{ 'country':'China', 'city':'henan' }}db.user.insertMany([user1,user2,user3,user4,user5])db.t1.insert({"_id":1,"a":"1","b":"2","c":"3"})db.t1.save({"_id":1,"z":"6"}) 有就用新的記錄覆蓋掉原來的記錄,無就新增
# SQL:=,!=,>,<,>=,<=# MongoDB:{key:value}代表什么等于什么"$ne"====>不等于"$gt"====>大于"$lt"====>小于"gte"====>大于等于"lte"====>小于等于 其中"$ne"能用于所有數(shù)據(jù)類型#1、select * from db1.user where name = "alex";db.user.find({'name':'alex'})#2、select * from db1.user where name != "alex";db.user.find({'name':{"$ne":'alex'}})#3、select * from db1.user where id > 2;db.user.find({'_id':{'$gt':2}})#4、select * from db1.user where id < 3;db.user.find({'_id':{'$lt':3}})#5、select * from db1.user where id >= 2;db.user.find({"_id":{"$gte":2,}})#6、select * from db1.user where id <= 2;db.user.find({"_id":{"$lte":2}})
# SQL:and,or,not# MongoDB:字典中逗號分隔的多個條件是and關(guān)系,"$or"的條件放到[]內(nèi),"$not"#1、select * from db1.user where id >= 2 and id < 4;db.user.find({'_id':{"$gte":2,"$lt":4}})#2、select * from db1.user where id >= 2 and age < 40;db.user.find({"_id":{"$gte":2},"age":{"$lt":40}})#3、select * from db1.user where id >= 5 or name = "alex";db.user.find({ "$or":[ {'_id':{"$gte":5}}, {"name":"alex"} ]})#4、select * from db1.user where id % 2=1;db.user.find({'_id':{"$mod":[2,1]}})#5、上題,取反db.user.find({'_id':{"$not":{"$mod":[2,1]}}})
# SQL:in,not in# MongoDB:"$in","$nin"#1、select * from db1.user where age in (20,30,31);db.user.find({"age":{"$in":[20,30,31]}})#2、select * from db1.user where name not in ('alex','yuanhao');db.user.find({"name":{"$nin":['alex','yuanhao']}})
# SQL: regexp 正則# MongoDB: /正則表達(dá)/i#1、select * from db1.user where name regexp '^j.*?(g|n)$';db.user.find({'name':/^j.*?(g|n)$/i})
#1、select name,age from db1.user where id=3;db.user.find({'_id':3},{'_id':0,'name':1,'age':1})1:代表要,類似True0:代表不要,類似Flase,默認(rèn)是0
#1、查看有dancing愛好的人db.user.find({'hobbies':'dancing'})#2、查看既有dancing愛好又有tea愛好的人db.user.find({ 'hobbies':{ "$all":['dancing','tea'] }})#3、查看第4個愛好為tea的人:".方法"db.user.find({"hobbies.3":'tea'})#4、查看所有人最后兩個愛好:"$slice"db.user.find({},{'hobbies':{"$slice":-2},"age":0,"_id":0,"name":0,"addr":0})#5、查看所有人的第2個到第3個愛好db.user.find({},{'hobbies':{"$slice":[1,2]},"age":0,"_id":0,"name":0,"addr":0})> db.blog.find().pretty(){ "_id" : 1, "name" : "sun7公司破產(chǎn)的真相", "comments" : [ { "name" : "zhang3", "content" : "sun7是誰???", "thumb" : 200 }, { "name" : "li4", "content" : "我去,真的假的", "thumb" : 300 }, { "name" : "wang5", "content" : "吃喝嫖賭抽,欠下兩個億", "thumb" : 40 }, { "name" : "zhao6", "content" : "丐幫歡迎你", "thumb" : 0 } ]}db.blog.find({},{'comments':{"$slice":-2}}).pretty() #查詢最后兩個db.blog.find({},{'comments':{"$slice":[1,2]}}).pretty() #查詢1到2
# 排序:1代表升序,-1代表降序db.user.find().sort({"name":1})db.user.find().sort({"age":-1,'_id':1})
# 分頁:limit代表取多少個document,skip代表跳過前多少個document。 db.user.find().sort({'age':1}).limit(1).skip(2)
# 獲取數(shù)量db.user.count({'age':{"$gt":30}}) --或者 db.user.find({'age':{"$gt":30}}).count()
#1、{'key':null} 匹配key的值為null或者沒有這個keydb.t2.insert({'a':10,'b':111})db.t2.insert({'a':20})db.t2.insert({'b':null})> db.t2.find({"b":null}){ "_id" : ObjectId("5a5cc2a7c1b4645aad959e5a"), "a" : 20 }{ "_id" : ObjectId("5a5cc2a8c1b4645aad959e5b"), "b" : null }#2、查找所有db.user.find() #等同于db.user.find({})db.user.find().pretty()#3、查找一個,與find用法一致,只是只取匹配成功的第一個db.user.findOne({"_id":{"$gt":3}})#4、去重db.user.find().distinct()
update() 方法用于更新已存在的文檔。語法格式如下: db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> })參數(shù)說明:對比update db1.t1 set name='zhangsan',sex='Male' where name='zhang3' and age=18;query : 相當(dāng)于where條件。 update : update的對象和一些更新的操作符(如$,$inc...等,相當(dāng)于set后面的 upsert : 可選,默認(rèn)為false,代表如果不存在update的記錄不更新也不插入,設(shè)置為true代表插入。 multi : 可選,默認(rèn)為false,代表只更新找到的第一條記錄,設(shè)為true,代表更新找到的全部記錄。 writeConcern :可選,拋出異常的級別。 更新操作是不可分割的:若兩個更新同時發(fā)送,先到達(dá)服務(wù)器的先執(zhí)行,然后執(zhí)行另外一個,不會破壞文檔。
#注意:除非是刪除,否則_id是始終不會變的#1、覆蓋式:db.user.update({'age':20},{"name":"wang5","hobbies_count":3})是用{"_id":2,"name":"wang5","hobbies_count":3}覆蓋原來的記錄#2、一種最簡單的更新就是用一個新的文檔完全替換匹配的文檔。這適用于大規(guī)模式遷移的情況。例如var obj=db.user.findOne({"_id":2})obj.username=obj.name+'SB'obj.hobbies_count++delete obj.age db.user.update({"_id":2},obj)
#設(shè)置:$set通常文檔只會有一部分需要更新??梢允褂迷有缘母滦薷钠?,指定對文檔中的某些字段進(jìn)行更新。 更新修改器是種特殊的鍵,用來指定復(fù)雜的更新操作,比如修改、增加后者刪除#1、update db1.user set name="wang5" where id = 2db.user.update({'_id':2},{"$set":{"name":"wang5",}})#2、沒有匹配成功則新增一條{"upsert":true}db.user.update({'_id':6},{"$set":{"name":"wang5","age":18}},{"upsert":true})#3、默認(rèn)只改匹配成功的第一條,{"multi":改多條}db.user.update({'_id':{"$gt":4}},{"$set":{"age":28}})db.user.update({'_id':{"$gt":4}},{"$set":{"age":38}},{"multi":true})#4、修改內(nèi)嵌文檔,把名字為wang5的人所在的地址國家改成Japandb.user.update({'name':"wang5"},{"$set":{"addr.country":"Japan"}})#5、把名字為wang5的人的地2個愛好改成piaodb.user.update({'name':"wang5"},{"$set":{"hobbies.1":"piao"}})#6、刪除wang5的愛好,$unsetdb.user.update({'name':"wang5"},{"$unset":{"hobbies":""}})
#增加和減少:$inc#1、所有人年齡增加一歲db.user.update({}, { "$inc":{"age":1} }, { "multi":true } )#2、所有人年齡減少5歲db.user.update({}, { "$inc":{"age":-5} }, { "multi":true } )
#添加刪除數(shù)組內(nèi)元素 往數(shù)組內(nèi)添加元素:$push#1、為名字為wang5的人添加一個愛好readdb.user.update({"name":"wang5"},{"$push":{"hobbies":"read"}})#2、為名字為wang5的人一次添加多個愛好tea,dancingdb.user.update({"name":"wang5"},{"$push":{ "hobbies":{"$each":["tea","dancing"]}}})按照位置且只能從開頭或結(jié)尾刪除元素:$pop#3、{"$pop":{"key":1}} 從數(shù)組末尾刪除一個元素db.user.update({"name":"wang5"},{"$pop":{ "hobbies":1}})#4、{"$pop":{"key":-1}} 從頭部刪除db.user.update({"name":"wang5"},{"$pop":{ "hobbies":-1}})#5、按照條件刪除元素,:"$pull" 把符合條件的統(tǒng)統(tǒng)刪掉,而$pop只能從兩端刪db.user.update({'addr.country':"China"},{"$pull":{ "hobbies":"read"}},{ "multi":true})
#避免添加重復(fù):"$addToSet"db.urls.insert({"_id":1,"urls":[]})db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})db.urls.update({"_id":1},{ "$addToSet":{ "urls":{ "$each":[ 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.xxxx.com' ] } } })
#1、了解:限制大小"$slice",只留最后n個db.user.update({"_id":5},{ "$push":{"hobbies":{ "$each":["read",'music','dancing'], "$slice":-2 } }})#2、了解:排序The $sort element value must be either 1 or -1"db.user.update({"_id":5},{ "$push":{"hobbies":{ "$each":["read",'music','dancing'], "$slice":-1, "$sort":-1 } }})#注意:不能只將"$slice"或者"$sort"與"$push"配合使用,且必須使用"$eah"
#1、刪除多個中的第一個db.user.deleteOne({ 'age': 8 })#2、刪除國家為China的全部db.user.deleteMany( {'addr.country': 'China'} ) #3、刪除全部db.user.deleteMany({})
如果你有數(shù)據(jù)存儲在MongoDB中,你想做的可能就不僅僅是將數(shù)據(jù)提取出來那么簡單了;你可能希望對數(shù)據(jù)進(jìn)行分析并加以利用。MongoDB提供了以下聚合工具:#1、聚合框架#2、MapReduce(詳見MongoDB權(quán)威指南)#3、幾個簡單聚合命令:count、distinct和group。(詳見MongoDB權(quán)威指南)#聚合框架:可以使用多個構(gòu)件創(chuàng)建一個管道,上一個構(gòu)件的結(jié)果傳給下一個構(gòu)件。 這些構(gòu)件包括(括號內(nèi)為構(gòu)件對應(yīng)的操作符):篩選($match)、投射($project)、分組($group)、排序($sort)、限制($limit)、跳過($skip)不同的管道操作符可以任意組合,重復(fù)使用
from pymongo import MongoClientimport datetime client=MongoClient('mongodb://root:123@localhost:27017')table=client['db1']['emp']# table.drop()l=[('tom','male',18,'20170301','校長',73000.33,401,1), #以下是教學(xué)部('bob','male',78,'20150302','teacher',10000.31,401,1),('sam','male',81,'20130305','teacher',8300,401,1),('zhang3','male',73,'20140701','teacher',3500,401,1),('li4','male',28,'20121101','teacher',2100,401,1),('may','female',18,'20110211','teacher',9000,401,1),('wang5','male',18,'19000301','teacher',30000,401,1),('成龍','male',48,'20101111','teacher',10000,401,1),('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是銷售部門('丫丫','female',38,'20101101','sale',2000.35,402,2),('丁丁','female',18,'20110312','sale',1000.37,402,2),('星星','female',18,'20160513','sale',3000.29,402,2),('格格','female',28,'20170127','sale',4000.33,402,2),('張野','male',28,'20160311','operation',10000.13,403,3), #以下是運(yùn)營部門('程咬金','male',18,'19970312','operation',20000,403,3),('程咬銀','female',18,'20130311','operation',19000,403,3),('程咬銅','male',18,'20150411','operation',18000,403,3),('程咬鐵','female',18,'20140512','operation',17000,403,3)]for n,item in enumerate(l): d={ "_id":n, 'name':item[0], 'sex':item[1], 'age':item[2], 'hire_date':datetime.datetime.strptime(item[3],'%Y%m%d'), 'post':item[4], 'salary':item[5] } table.save(d)
{"$match":{"字段":"條件"}},可以使用任何常用查詢操作符$gt,$lt,$in等#例1、select * from db1.emp where post='teacher';db.emp.aggregate({"$match":{"post":"teacher"}})#例2、select * from db1.emp where id > 3 group by post; db.emp.aggregate( {"$match":{"_id":{"$gt":3}}}, {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}})#例3、select * from db1.emp where id > 3 group by post having avg(salary) > 10000; db.emp.aggregate( {"$match":{"_id":{"$gt":3}}}, {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}}, {"$match":{"avg_salary":{"$gt":10000}}})
{"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表達(dá)式"}}#1、select name,post,(age+1) as new_age from db1.emp;db.emp.aggregate( {"$project":{ "name":1, "post":1, "new_age":{"$add":["$age",1]} }})#2、表達(dá)式之?dāng)?shù)學(xué)表達(dá)式{"$add":[expr1,expr2,...,exprN]} #相加{"$subtract":[expr1,expr2]} #第一個減第二個{"$multiply":[expr1,expr2,...,exprN]} #相乘{(lán)"$pide":[expr1,expr2]} #第一個表達(dá)式除以第二個表達(dá)式的商作為結(jié)果{"$mod":[expr1,expr2]} #第一個表達(dá)式除以第二個表達(dá)式得到的余數(shù)作為結(jié)果#3、表達(dá)式之日期表達(dá)式:$year,$month,$week,$dayOfMonth,$dayOfWeek,$dayOfYear,$hour,$minute,$second#例如:select name,date_format("%Y") as hire_year from db1.empdb.emp.aggregate( {"$project":{"name":1,"hire_year":{"$year":"$hire_date"}}})#例如查看每個員工的工作多長時間db.emp.aggregate( {"$project":{"name":1,"hire_period":{ "$subtract":[ {"$year":new Date()}, {"$year":"$hire_date"} ] }}})#4、字符串表達(dá)式{"$substr":[字符串/$值為字符串的字段名,起始位置,截取幾個字節(jié)]}{"$concat":[expr1,expr2,...,exprN]} #指定的表達(dá)式或字符串連接在一起返回,只支持字符串拼接{"$toLower":expr}{"$toUpper":expr}db.emp.aggregate( {"$project":{"NAME":{"$toUpper":"$name"}}})#5、邏輯表達(dá)式$and$or$not其他見Mongodb權(quán)威指南
{"$group":{"_id":分組字段,"新的字段名":聚合操作符}}#1、將分組字段傳給$group函數(shù)的_id字段即可{"$group":{"_id":"$sex"}} #按照性別分組{"$group":{"_id":"$post"}} #按照職位分組{"$group":{"_id":{"state":"$state","city":"$city"}}} #按照多個字段分組,比如按照州市分組#2、分組后聚合得結(jié)果,類似于sql中聚合函數(shù)的聚合操作符:$sum、$avg、$max、$min、$first、$last#例1:select post,max(salary) from db1.emp group by post; db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}})#例2:去每個部門最大薪資與最低薪資db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}})#例3:如果字段是排序后的,那么$first,$last會很有用,比用$max和$min效率高db.emp.aggregate({"$group":{"_id":"$post","first_id":{"$first":"$_id"}}})#例4:求每個部門的總工資db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":"$salary"}}})#例5:求每個部門的人數(shù)db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":1}}})#3、數(shù)組操作符{"$addToSet":expr}:不重復(fù){"$push":expr}:重復(fù)#例:查詢崗位名以及各崗位內(nèi)的員工姓名:select post,group_concat(name) from db1.emp group by post;db.emp.aggregate({"$group":{"_id":"$post","names":{"$push":"$name"}}})db.emp.aggregate({"$group":{"_id":"$post","names":{"$addToSet":"$name"}}})
{"$sort":{"字段名":1,"字段名":-1}} #1升序,-1降序{"$limit":n} {"$skip":n} #跳過多少個文檔#例1、取平均工資最高的前兩個部門db.emp.aggregate({ "$group":{"_id":"$post","平均工資":{"$avg":"$salary"}}},{ "$sort":{"平均工資":-1}},{ "$limit":2})#例2、db.emp.aggregate({ "$group":{"_id":"$post","平均工資":{"$avg":"$salary"}}},{ "$sort":{"平均工資":-1}},{ "$limit":2},{ "$skip":1})
#集合users包含的文檔如下{ "_id" : 1, "name" : "dave123", "q1" : true, "q2" : true }{ "_id" : 2, "name" : "dave2", "q1" : false, "q2" : false }{ "_id" : 3, "name" : "ahn", "q1" : true, "q2" : true }{ "_id" : 4, "name" : "li", "q1" : true, "q2" : false }{ "_id" : 5, "name" : "annT", "q1" : false, "q2" : true }{ "_id" : 6, "name" : "li", "q1" : true, "q2" : true }{ "_id" : 7, "name" : "ty", "q1" : false, "q2" : true }#下述操作時從users集合中隨機(jī)選取3個文檔db.users.aggregate( [ { $sample: { size: 3 } } ])
以上是“一篇文章教會你如何操作MongoDB”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。