MongoDB: 非關系型數據庫
?? ?
文件管理階段:
優點:?
?? ?可以長期保存
?? ?存儲大量數據
?? ?使用簡單
缺點:
?? ?數據一致性差
?? ?數據大的時候,查找修改不便
?? ?隨著時間增長,冗余度大
?? ?
數據庫管理階段:
優點:?? ?
?? ?降低冗余度
?? ?提高增刪改查效率
?? ?易擴展
?? ?方便調用和自動化處理
?? ?
缺點:上手相對復雜
數據: 能夠輸入到計算機中,并被識別處理的信息集合
數據結構:計算機存儲、組織數據的方式;
數據庫:按照一定數據結構存儲管理數據的倉庫。 在數據庫管理系統管理和控制下,在一定介質上的數據集合
數據庫管理系統:管理數據庫的軟件,用于建立和維護數據庫
數據庫系統:由數據庫管理系統和數據庫 ,開發工具等組成的集合
關系型數據庫:
?? ?采用關系模型來組織數據結構的數據庫(二維表)
?? ?Oracle ?DB2 ?SQLServer Mysql sqLite(Python標準庫支持)
優點: ?? ?
?? ??? ?容易理解,類似常見的表格
?? ??? ?使用方便,sql語句
?? ??? ?數據一致性高,冗余度低,完整性好
?? ??? ?技術成熟, 可以使用外部鏈接等比較復雜的操作
?? ??? ?
缺點:?? ?
?? ??? ?不能很好滿足高并發需求,每次都需要進行sql語句的解析
?? ??? ?針對海量數據的瞬間爆發,讀寫性能不足,關系型數據庫內部的每部操作需要加鎖保證操作的原子性
?? ??? ?數據擴展普遍比非關系困難
?? ??? ?數據一致性高,有時會浪費大量空間
?? ?
非關系型數據庫NoSql(Not only Sql):
優點:?
?? ??? ?高并發,大數據讀寫能力強
?? ??? ?支持分布式,易擴展
?? ??? ?弱化了數據結構,降低了數據的一致性
?? ??? ?
缺點:
?? ??? ?通用性差,沒有 像sql那樣的一致性操作
?? ??? ?操作靈活,容易混亂
?? ??? ?沒有join,有的數據庫事物支持等操作
?? ??? ?
Nosql使用場景:
?? ?1, 數據一致性要求低
?? ?2, 數據庫 并發處理要求高
?? ?3, 數據庫設計時,對大小的估算不確定,需要分布拓展
?? ?4, 給定的數據比較容易建立起Nosql模型
?? ?
?? ?
Nosql分類:
?? ?1,KEY-VALUE : Redis, oracle BDB , Tokyo
?? ?2,列存儲數據庫: ?HBase
?? ?3,文檔型數據庫: ?MongoDB, CouchDB
?? ?4,圖形數據庫:Neo4j、FlockDB
?? ?
?? ?
MongoDB:
1, C++ 編寫的數據庫管理系統
2,支持非常豐富的增刪改查數據操作
3,支持非常豐富的數據類型
4,使用方便,便于部署,支持分布,容易拓展
5,支持眾多的編程語言接口(python, ruby, c++ , c#, PHP)
設計數據庫:
微信朋友圈--mysql:
user: id, 昵稱, 性別, 電話, 地區;
朋友圈: infoid, 用戶id, 文字內容, 圖片路徑, 視頻路徑,發布時間,地點, ?有效時間
評論: infoid 評論, 點贊數量, 點贊userid
MONGODB:
{
name:zhang,?
age: 20,?
sex:m,?
friendspace:
?? ?[
?? ?{
?? ?id:1,
?? ?content:去臺灣插紅旗,?
?? ?comment:{
?? ??? ??? ?li:牛逼,?
?? ??? ??? ?wang: 膽兒大,?
?? ??? ??? ?hu:敢去插紅旗
?? ??? ??? ?hua: 6666}
?? ?},
?? ?{
?? ?id:2,?
?? ?content: 旅游
?? ?comment:{zhou: 帶上我}
?? ?}
?? ?]
}
MONGOD Install(開源):
自動安裝: yum install mangodb
?? ?默認路徑:/var/lib/mongodb
?? ?配置文件: /etc/mongodb.conf
?? ?命令集:
手動安裝:?
?? ??? ??? ??? ?
PATH=$PATH:/export/servers/mongodb-linux-x86_64-rhel62-3.4.10/bin
export PATH
?? ??? ??? ??? ?
設置數據存儲位置: ?mongod --dbpath path
指定端口號,--port ? 默認27017
mongo 進入mongo shell界面
退出界面: quit()?
組成結構: 鍵值對-->文檔 --> 集合 --> 數據庫
?
mysql和mongodb對比
mysql:
id?? ??? ??? ?name?? ??? ??? ?age
1?? ??? ??? ?lulijuan?? ??? ?18
2?? ??? ??? ?wanghuan?? ??? ?20
3?? ??? ??? ?fuyalin?? ??? ??? ?20
mongodb:
{
?? ?"id":ObjectId("abcd12345fasds"), ? --id由系統自動生成
?? ?"name":"lulijuan"
?? ?"age":18
},
{
?? ?"id":ObjectId("abcd12345fasds"),
?? ?"name":"wanghuan"
?? ?"age":20
},
{
?? ?"id":ObjectId("abcd12345fasds"),
?? ?"name":"fuyalin"
?? ?"age":20
}
-------------------------------------------
mysql?? ??? ??? ?mongodb?? ??? ??? ?含義
-------------------------------------------
database?? ??? ?database?? ??? ?數據庫
table?? ??? ??? ?collection?? ??? ?表/集合
column?? ??? ??? ?field?? ??? ??? ?字段/域
row?? ??? ??? ??? ?document?? ??? ?記錄/文檔
index?? ??? ??? ?index?? ??? ??? ?索引
-------------------------------------------
創建數據庫,use db,不存在則創建,并切換;如果已存在則切換;
使用use之后,并不會馬上創建,而是插入后才會創建
> ?use test
switched to db test
查看數據庫:?
> show dbs
admin ?0.000GB
local ?0.000GB
test ? 0.000GB
>
數據庫名稱規則:
1, 原則上滿足 utf-8字符
2, 不能是空字符,不能含有空格,點, / ?\ ?\0等
3, 習慣上英文小寫
4, 長度不超過64字節
5, 不能使用: admin, local,config等
系統數據庫介紹:
admin: 存儲用戶
local: 存儲本地數據
config: 存儲分片配置信息
db: mongodb全局變量,顯示當前正在使用的數據庫;相當于select database();默認為: test如果插入數據,即默認創建test數據庫
MONGODB備份和恢復
備份:mongodump -h dbhost -d dbname -o dbdir
?? ?eg:?
?? ??? ?mongodump -h 127.0.0.1 -o /tmp -d test
?? ??? ?2019-06-15T19:44:19.236+0800?? ?writing test.class1 to
?? ??? ?2019-06-15T19:44:19.238+0800?? ?done dumping test.class1 (1 document)
?? ??? ?
?? ?將本機下test 庫備份導/tmp文件夾中,會生成一個與庫名同名的文件夾
?? ?
?? ?[root@A02-R05-I45-170-J33FE0D test]# ls /tmp/test/
?? ?class1.bson ?class1.metadata.json
恢復:
?? ?mongorestore -h
?? ?eg:
?? ??? ?將備份/tmp/test恢復到本機llj庫
?? ??? ?[root@A02-R05-I45-170-J33FE0D test]# mongorestore -h 127.0.0.1:27017 -d llj /tmp/test
?? ?
?? ??? ?
數據庫檢測:
?? ?mongostat 系統會每秒會檢測一次
?? ?insert query update delete getmore command dirty used flushes vsize ? res qrw arw net_in net_out conn ? ? time
? ? *0 ? ?*0 ? ? *0 ? ? *0 ? ? ? 0 ? ? 2|0 ?0.0% 0.0% ? ? ? 0 ?996M 54.0M 0|0 1|0 ? 158b ? 46.5k ? ?2 Jun 15 19:55:05.861
? ? *0 ? ?*0 ? ? *0 ? ? *0 ? ? ? 0 ? ? 2|0 ?0.0% 0.0% ? ? ? 0 ?996M 54.0M 0|0 1|0 ? 158b ? 46.4k ? ?2 Jun 15 19:55:06.861
? ? *0 ? ?*0 ? ? *0 ? ? *0 ? ? ? 0 ? ? 1|0 ?0.0% 0.0% ? ? ? 0 ?996M 54.0M 0|0 1|0 ? 157b ? 46.2k ? ?2 Jun 15 19:55:07.863
? ? *0 ? ?*0 ? ? *0 ? ? *0 ? ? ? 0 ? ? 2|0 ?0.0% 0.0% ? ? ? 0 ?996M 54.0M 0|0 1|0 ? 158b ? 46.5k ? ?2 Jun 15 19:55:08.860
?? ?
?? ?insert/query/update/delete 每秒增刪改查次數
?? ?getmore command: 每秒運行命令的次數
?? ?dirty used flushes 每秒操作磁盤次數
?? ?vsize ?res: 使用虛擬內存和物理內存
?? ?
?? ?
mongotop ?分別監控每個庫,讀寫時長
刪除數據庫
先use到對應庫下,然后
db.dropDatabase(); 區分大小寫,調用dropDatabase()函數完成
集合的創建,切換到需要的庫下
db.createCollection(collection_name);
?? ?
or
當向一個 集合插入文檔的時候,如果該集合不存在,則自動創建
?? ?> db.class0.insert({'user':'wanghuan'})
?? ?WriteResult({ "nInserted" : 1 })
?? ?>
?? ?
查看集合:
show tables;
show collections;
集合命名規則:
1, 不能為空字符串,不能有\0
2, 不能和關鍵字重復
3, 不能以system. 開頭,這是系統集合的保留前綴
刪除集合:
db.collectionsname.drop()
eg:
?? ?tables
?? ?> db.class0.drop()
?? ?true
?? ?>
?? ?> db.class1.drop()
?? ?true
重名名集合
db.collectionName.renameCollection('new_name')
文檔:的組織形式
文檔的組成形式是bson,類似字典(實際不是字典),也是由key-value對組成
鍵值對組成文檔 ---> 類似python字典
而是bson ---> json ---> ?JaveScript
文檔中,鍵的命名規則:
1, utf-8字符
2, 不可以\0, 習慣上不用. 和 $
3, 以_開頭的多為保留鍵,自定義KEY一般不以_開頭
注意:1,bson 鍵值對是有序的;
?? ? ?2, mongodb中嚴格區分大小寫
值:?? ?mongodb的支持數據類型;
MONGODB支持的數據類型:
Type?? ??? ??? ?Value
整型:?? ??? ??? ?整數
布爾bool:?? ??? ?true/false
浮點型: ?? ??? ?小數
Arrays?? ??? ??? ?數組類型
Timestamp?? ??? ?時間戳
Date?? ??? ??? ?日期
Object?? ??? ??? ?內部文檔
Null?? ??? ??? ?空值
Symbol?? ??? ??? ?特殊字符
String?? ??? ??? ?字符串
Bianry data?? ??? ?二進制字符串
code?? ??? ??? ?代碼
regex?? ??? ??? ?正則表達式
ObjectId?? ??? ?ObjectId子串,保證唯一,用于主鍵
ObjectId:?? ??? ?系統自動為每個文檔生成的不重復的主鍵
?? ??? ??? ??? ?Key:_id
?? ??? ??? ??? ?Value: ObjectId("5d04d6e58734885c8b20206f")
24位 16進制數; 8位文檔創建時間 + 6位機器ID + 4位進程ID + 6位計數器
文檔特點:
?? ?1, 集合中的文檔不一定相同, 不保證數據一致性
?? ?2, 集合中文檔結構不一定相同;
?? ?
設計原則:
?? ?1, 集合中文檔盡可能描述的數據類似
?? ?2, 同一類文檔放在相同集合,不同文檔分集合存放
?? ?3, 文檔嵌套層次不宜太多
?? ?
插入文檔 ---做為文檔插入,key可以不加引號
db.collectionName.insert()
> db.wanghuan.insert({'name':'wanghuan', 'age':18, 'sex':'yes'})
WriteResult({ "nInserted" : 1 })
插入多條文檔:?
db.collectionName.insert([{},{},{}])
db.collectionName.save()
如果不加_id, 則作用和insert()一致
如果加_id,當沒有重復_id值的時候,和insert()一致,如果有重復_id,則update文檔
save()方法無法一次插入多個文檔
> db.wanghuan.insert([{name:'suhuanhuan', age:18, score:90},{name:'hanxiaojuan', age:22, score:84},{name:'yanqiao', age:19, score:99}])
BulkWriteResult({
?? ?"writeErrors" : [ ],
?? ?"writeConcernErrors" : [ ],
?? ?"nInserted" : 3,
?? ?"nUpserted" : 0,
?? ?"nMatched" : 0,
?? ?"nModified" : 0,
?? ?"nRemoved" : 0,
?? ?"upserted" : [ ]
查找文檔?
db.collectionName.find()
> db.wanghuan.find()
{ "_id" : ObjectId("5d05eef59886363f8a94a74c"), "name" : "wanghuan", "age" : 18, "sex" : "yes" }
>
面試問題:關系型數據庫和非關系型數據庫特點
?? ??? ??? ?mongodb優點:
find(query,field)
功能: 查找所有符合條件的文檔
參數:?
query: 篩選條件,相當于where子句
field: 展示的域,相當于select展示部分
field: 傳一組鍵值對, 鍵表示域名,值表示是否顯示,0否,1是
如果某個域給0,則不顯示該域,其他域默認顯示;?
如果某個域設置1,則顯示該域,其他域默認不顯示;
_id默認都是顯示的
要么都設置0,要么都是1;不可以混用,除_id
?? ?> db.llj.find({},{_id:0,name:1,age:1})
?? ?{ "name" : "wanghuan", "age" : 18 }
?? ?{ "name" : "wanghuan", "age" : 18 }
?? ?{ "name" : "suhuanhuan", "age" : 18 }
?? ?{ "name" : "yanqiao", "age" : 18 }
?? ?>
> db.llj.find({},{_id:0,name:0,age:0})
{ "sex" : "yes" }
{ "sex" : "yes" }
{ "sex" : "yes" }
{ "sex" : "yes" }
> db.llj.find({},{name:1,age:1})
{ "_id" : ObjectId("5d05eef59886363f8a94a74c"), "name" : "wanghuan", "age" : 18 }
{ "_id" : 1, "name" : "wanghuan", "age" : 18 }
{ "_id" : 2, "name" : "suhuanhuan", "age" : 18 }
{ "_id" : 3, "name" : "yanqiao", "age" : 18 }
>
query:
> db.llj.find({age:17},{_id:0,name:1,age:1})
{ "name" : "yanqiao", "age" : 17 }
>
>
> db.llj.find({age:18},{_id:0,name:1,age:1})
{ "name" : "wanghuan", "age" : 18 }
{ "name" : "suhuanhuan", "age" : 18 }
findOne() ?顯示查找結果的第一條數據,類似limit1
> db.llj.findOne({age:18},{})
{
?? ?"_id" : ObjectId("5d05eef59886363f8a94a74c"),
?? ?"name" : "wanghuan",
?? ?"age" : 18,
?? ?"sex" : "yes"
}
操作符:
$ 表名一個特殊字符,表示特殊含義:
比較操作符:
?? ?$eq?? ?等于
?? ?$gt 大于
?? ?$lt?? ?小于
?? ?$ne 不等于
?? ?$gte 大于等于?? ?great equal
?? ?$lte 小于等于?? ?less equal
?? ?$in ?包含
?? ?$nin 不包含?? ??? ?not in
?? ?
邏輯操作符:
?? ?$and ?? ?邏輯與
?? ?$or?? ??? ?邏輯或
?? ?$not?? ?邏輯非
?? ?$nor?? ?既不也不,表示集合中的條件都不具備
?? ?
?? ?
example:
> db.llj.find({age:{$gt:20}},{_id:0})
{ "name" : "玄冥", "age" : 100, "sex" : "yes" }
{ "name" : "祝融", "age" : 99, "sex" : "yes" }
{ "name" : "東皇", "age" : 1000, "sex" : "no" }
>
>
> db.llj.find({age:{$in:[18,20]}},{_id:0})
{ "name" : "wanghuan", "age" : 18, "sex" : "yes" }
{ "name" : "suhuanhuan", "age" : 18, "sex" : "yes" }
{ "name" : "南落", "age" : 20, "sex" : "no" }
>
>
> db.llj.find({age:{$gte:18,$lte:20}},{_id:0})
{ "name" : "wanghuan", "age" : 18, "sex" : "yes" }
{ "name" : "wanghuan", "age" : 19, "sex" : "yes" }
{ "name" : "suhuanhuan", "age" : 18, "sex" : "yes" }
{ "name" : "南落", "age" : 20, "sex" : "no" }
> db.llj.find({$and:[{age:18},{name:'suhuanhuan'}]},{})
> db.llj.find({$or:[{age:{$eq:100}},{name:'suhuanhuan'}]},{})
> db.llj.find({$or:[{age:{$lte:17}},{age:{$gte:99}}]},{_id:0})
> db.llj.find({sex:{$not:{$eq:'no'}}},{_id:0})
> db.llj.find({age:{$not:{$eq:18}}},{})
> db.llj.find({age:{$nin:[18,17,20]}},{})
> db.llj.find({$and:[{$or:[{age:{$gt:20}},{name:'yanqiao'}]},{sex:'yes'}]},{_id:0})
查看數組中包含travel的文檔
> db.wanghuan.find({hobby:'travel'},{})
{ "_id" : ObjectId("5d08832d1d8137d607c20d1c"), "name" : "yanqiao", "hobby" : [ "sleeping", "shopping", "travel" ] }
{ "_id" : ObjectId("5d0883ba1d8137d607c20d1d"), "name" : "suhuanhuan", "hobby" : [ "loveme", "beautiful", "travel" ] }
>
$all 查找數組中,同時包含多個值的文檔
$size 查找數組元素個數為指定數量的文檔
$slice 數組切片顯示?
$exists 判斷一個域是否存在
$mod ?整除查找,除以某個數余某個數
$type 查找指定類型的文檔
類型參考:
?? ?https://docs.mongodb.com/manual/reference/operator/query/type/
?? ?
> db.wanghuan.find({hobby:{$all:['travel','shopping']}},{})
{ "_id" : ObjectId("5d08832d1d8137d607c20d1c"), "name" : "yanqiao", "hobby" : [ "sleeping", "shopping", "travel" ] }
> db.wanghuan.find({hobby:{$size:3}},{})
db.wanghuan.find({},{_id:0, hobby:{$slice:-2}})
查找包含sex域的文檔;
> db.wanghuan.find({sex:{$exists:true}},{_id:0})
{ "name" : "wanghuan", "age" : 18, "sex" : "yes" }
{ "name" : "llj", "age" : 20, "sex" : "great" }
{ "name" : "llj", "age" : 20, "sex" : "great" }
查找年齡是奇數的人: {$mod:[2,1]}除以2余1
> db.wanghuan.find({age:{$mod:[2,1]}},{_id:0})
> db.wanghuan.find({_id:{$type:7}})
函數:
distinct() ?? ?查看一個集合中,某個域值的覆蓋范圍
pretty() ? ?? ?將查詢結果格式化顯示
limit(n)?? ?查詢結果顯示前n條
skip(n)?? ??? ?顯示時跳過前n條
count()?? ??? ?對顯示結果計數統計
sort({field:1/-1})?? ??? ?對查找結果,根據指定域進行排序,1升序、-1降序,復合排序,當第一排序項相同的時候按照第二排序項排序
eg:
> db.ming.distinct('skill')
> db.llj.distinct('name')
> db.llj.find().pretty()
> db.ming.find().limit(3)
> db.ming.find().skip(3)?? ?
> db.nanluo.find({sex:'yes'}).count()
> db.nanluo.find({age:{$exists:true}},{_id:0}).sort({age:-1})
> db.nanluo.find({age:{$exists:true}},{_id:0}).sort({age:1, name:1})
> db.nanluo.find({age:{$exists:true}},{_id:0}).sort({age:1}).limit(3)
刪除文檔
db.collectionName.remove(query,justOne)
功能:?? ?刪除指定文檔
參數:?? ?query:?? ?篩選條件 ,類似where子句,用法通查詢操作
?? ??? ?justOne:?? ?bool值,默認false,表示刪除所有匹配條件
?? ??? ??? ??? ??? ?如果為true,則只刪除符合匹配條件一條;
?? ??? ??? ??? ??? ?
刪除存在score域的一條記錄
db.wanghuan.remove({score:{exists:true}},true)
刪除不存在age域的所有記錄
db.wanghuan.remove({age:{$exists:false}})
db.wanghuan.remove({}) 刪除集合中所有文檔;
修改:
db.collectionName.update(query, update,upsert,multi)
功能: 修改一個文檔
參數:?? ?query: ?? ?刪除要修改的文檔,相當于where ,用法同查找
?? ??? ?update:?? ?將數據更新為內容,相當于set,需要使用修改器操作符
?? ??? ?upsert: bool, 默認為false: 如果query的文檔不存在則無法修改
?? ??? ??? ??? ?如果為true: 表示如果query的文檔不存在,則根據query和update參數插入新文檔
?? ??? ?multi: bool值, 默認為false: 如果有多條符合篩選條件的文檔,只修改第一條
?? ??? ??? ??? ?如果設置為true,則修改所有符合條件的文檔
?? ??? ??? ??? ?
$set: ?? ?修改一個域的值
?? ??? ?增加一個域
?? ??? ?刪除一個域
$unset: 刪除一個域; {$unset:{field:0/1}} 0或者1大都表示刪除
$rename: ?{$rename:{oldname:newname}}?? ?重命名一個域?? ?
$setOnInsert 如果操作插入新的文檔,則補充插入$setOnInsert內容; 如果不插入;如果已經有該記錄,則不做操作
$inc?? ??? ?對field進行加減修改,需要是數值型(int,float,負數即可)
$mul?? ??? ?乘法修改器; 乘以某個數(小數,整數,負數皆可)
$min?? ??? ?設定最小值, 如果query域的值小于$min設置的值則不修改,如果大于則改為min值,設置上限
$max?? ??? ?設定最大值,如果query域的值大于$max,則不修改,如果小于max值則修改為max值;設置下限
?? ??? ??
?? ?
?? ??? ??? ??? ?
eg:?? ??? ?
將姓zhang的年齡修改為20
> db.class.update({name:'zhang'},{$set:{age:20}})
姓zhang的年齡修改為20,并且sex改為m
> db.class.update({name:'zhang'},{$set:{age:20, sex:'mm'}})
年齡大于等于10歲的所有人,年齡改為11
> db.class.update({age:{$gte:10}},{$set:{age:11}},false,true)
刪除一個域
> db.class.update({name:'wang'},{$unset:{hobby:0, sex:0}})
> db.example.update({}, {$unset: {words:1}}, false, true);
增加一個域
db.class.update({name:'zheng'},{$set:{weapon:'gun'}})
重命名字段名
db.class.update({},{$rename:{sex:'gener'}},false,true)
db.class.update({name:'chen'},{$set:{age:25}, $setOnInsert:{sex:'m',heigh:175}},true)
> db.class.update({age:{$lt:100}},{$inc:{age:-10}},false,true)
db.class.update({},{$mul:{age:0.5}},false,true)
> db.class.update({},{$min:{age:7}},false,true)
MONGODB練習:
1,創建數據庫,名字grade
2, 創建集合名字class
3, 集合中插入若干數據,文檔格式如下:
?? ?{name:'zhang', age:10, ?sex:'m', hobby:['a','b','c']}
?? ?hobby: draw, singing, dancing, basetball, football, pingpong, computer
4, 查找
?? ?a, 查看班級所有人信息
?? ?b, 查看班級中年齡為8歲的學生信息
?? ?c, 查看年齡大于10歲的學生信息
?? ?d, 查看年齡在4-8歲的學生信息
?? ?e, 找到年齡為6歲,且為男生的學生信息
?? ?f, 找到年齡小于7歲,大于10歲的學生
?? ?g, 找到年齡是8歲或者11歲的學生
?? ??? ?db.class.find({age:{$in:[8,11]}})
?? ??? ?db.class.find({$or:[{age:8},{age:11}]})
?? ?h, 找到興趣愛好有2項的學生
?? ??? ?db.class.find({hobby:{$size:2}})
?? ?i, 找到興趣愛好有draw的學生
?? ??? ?db.class.find({hobby:'draw'})
?? ?j, 找到既喜歡畫畫又喜歡跳舞的學生
?? ??? ?db.class.find({hobby:{$all:['draw','dancing']}})
?? ?k, 統計愛好有三項的學生人數
?? ??? ?db.class.find({hobby:{$size:3}})
?? ?l, 找出本班年齡第二大的學生
?? ??? ?db.class.find().sort({age:-1}).skip(1).limit(1)
?? ?m, 查找學生的興趣范圍
?? ??? ? db.class.distinct('hobby')
?? ?n, 將學生按照年齡排序,找到年齡最大的三個
?? ??? ?db.class.find().sort({age:-1}).limit(3)
?? ?o, 刪除所有年齡大于12或者小于4歲的學生
?? ??? ?db.class.remove({$or:[{age:{$gt:12}},{age:{$lt:4}}]},false)
?? ?
?? ?
數組修改器:當值為數組的時候,如何進行修改
$push?? ?向數組中添加一項
$pushAll 向數組中添加多項
$each?? ?逐個操作
$position?? ?選擇在數組特定位置進行操作必須要與each合用
$sort?? ??? ?對數組排序,必須與each合用;1 表示升序,-1降序
$pull?? ??? ?從數組中刪除一個元素
$pullAll?? ?從數組中刪除多個元素
$pop?? ??? ?從數組中彈出一個元素,第一個或者最后一個
$addToSet?? ?想數組中插入一個元素,該元素不能和其他元素重復;
數組下標:?? ?使用數組的時候,可以用.index 的方式使用數據的具體某一項;> db.class1.find({'score.0':{$gte:100}})
eg
> db.class1.update({name:'llj'},{$push:{score:60}})
> db.class1.update({name:'wanghuan'},{$pushAll:{score:[101,102]}})
> db.class1.update({name:'suhuanhuan'},{$push:{score:{$each:[103,104]}}},false,true)
> db.class1.update({name:'fantingting'},{$push:{score:{$each:[10,20],$position:1}}})
> db.class1.update({name:'fantingting'},{$push:{score:{$each:[],$sort:1}}})
> db.class1.update({name:'fantingting'}, {$pull:{score:20}})
> db.class1.update({name:'llj'},{$pullAll:{score:[60,91]}})
> db.class1.update({name:'wanghuan'},{$pop:{score:-1}})?? ?彈出第一項
> db.class1.update({name:'wanghuan'},{$pop:{score:1}}) 彈出最后一項
> db.class1.update({name:'wanghuan'},{$addToSet:{score:91}})
類型補充說明:
?? ?mongo中存儲時間的格式:ISODate
時間函數:?
?? ?new Date()
?? ?ISODate()
?? ?Date()
?? ?valueOf()?? ? 將時間轉換為時間戳類似timestamp()
?? ?
方法一: 自動生成當前時間
> db.book.insert({name:'Python入門', date:new Date()})
方法二:?
> db.book.insert({name:'算法結構', date:ISODate()})
方法三:?
> db.book.insert({name:'算法結構', date:Date()})
{ "_id" : ObjectId("5d0b2ed5598f12d353bbc53b"), "name" : "Python入門", "date" : ISODate("2019-06-20T06:59:33.784Z") }
{ "_id" : ObjectId("5d0b2f28598f12d353bbc53c"), "name" : "算法結構", "date" : ISODate("2019-06-20T07:00:56.017Z") }
{ "_id" : ObjectId("5d0b2f90598f12d353bbc53d"), "name" : "算法結構", "date" : "Thu Jun 20 2019 15:02:40 GMT+0800 (CST)" }
>
指定時間:
db.book.insert({name:'爬蟲',date:ISODate('2019-06-01 00:00:00')})
db.book.insert({name:'神奇的數學',date:ISODate('20190603')})
> db.book.insert({name:'神奇的數學',date:ISODate('20190603').valueOf()})
null
1, 如果某個域存在 卻沒有值,可以設置為null
2, 如果某個域不存在可以通過null匹配
> db.class.find({sex:null})
> db.class1.find({date:null})
Object類型:值是一個 文檔,文檔嵌套
> db.book.insert({name:'pthon Black&white', date:ISODate(), auth:{first:'wang', sec:'change'}})
嵌套文檔值的查找
> db.book.find({'auth.first':'wang'})
修改練習:
1, 小紅的年齡改為8歲,興趣愛好改為: dancing, draw
?? ?> db.class.update({name:'zheng'},{$set:{age:8,hobby:['dancing','draw']}})
2, 追加小紅的興趣愛好,singing
?? ?> db.class.update({name:'zhao'},{$push:{hobby:'singing'}})
3, 小王增加興趣愛好:basketball, 吹牛
?? ?> db.class.update({name:'wang'},{$set:{"name" : "wang", "age" : 10, hobby:['chuiniu','basketball']}})
4, 小李增加興趣愛好,running, singing, 不要和以前重復
?? ?> db.class.update({name:'li'},{$addToSet:{hobby:{$each:['running','singing','fucking']}}})
5, 班上所有同學年齡+1
?? ?> db.class.update({age:{$exists:1}}, {$inc:{age:1}}, false,true)
6, 刪除小明的sex屬性
?? ?> db.class.update({name:'wu'},{$unset:{sex:1}}
7, 刪除小李興趣中的第一項
?? ?> db.class.update({name:'li'},{$pop:{hobby:-1}})
8, 小紅興趣中的draw愛好刪除
?? ?> db.class.update({name:'zheng'},{$pull:{hobby:'draw'}})
索引:
?? ?指的是建立指定鍵值即所在文檔中存儲位置的對照清單,使用索引可以方便我們進行快速查找,減少遍歷次數,提高查找效率
?? ?
ensureIndex(field, index_type)?? ?創建索引
參數:?? ?索引類別,索引選項
?? ??? ?field:?? ?域名
?? ??? ?_id域 會自動創建索引
?? ??? ?1表示正向索引,-1表示逆向索引; 想要查找更老的數據還是想要查看更新的數據
查看索引:?? ??? ?
db.class.getIndexes()
刪除索引:
dropIndex('index_name') or dropIndex({field_name:1})
dropIndexes() 刪除所有索引
復合索引:根據多個字段創建索引
數組索引: 如果對數據域創建索引,俺么表示對數組中每個值俊創建了索引;通過數組中單個值的查詢也是索引查詢
子文檔索引:如果一個域 創建索引,值是一個文檔的,則該文檔的所有子文檔查找,均為索引查找;
?? ?如果對子文檔的某個域添加索引,則只能對子文檔中的該域查找才會形成索引,子文檔其他域的查找不是索引查找
?? ?
覆蓋索引,查找時只獲取所影項的內容;而不必獲取元數據的其他內容;這樣就不用連接原來數據,直接返回即可,提高查找效率;
唯一索引:?? ?創建索引時, 索引域的值均不相同,也可以據此限制一個域的值;創建了唯一索引后,不允許再插入該域相同值的文檔;
> db.class.ensureIndex({name:1},{unique:true})
稀疏索引(間隙索引):針對有指定域的文檔創建索引表,沒有該域的文檔不會插入到索引表中;
> db.class.ensureIndex({hobby:1},{sparse:true})
索引約束:
?? ?1, 影響數據的插入,刪除,更新操作,當數據發生改變的時,索引表必須同步更新
?? ?2, 索引也是需要占用一定空間資源
?? ?
綜上:
?? ?1, 當數據庫大量的操作是插入,修改,刪除操作,而非查詢操作時,不適合創建索引
?? ?2, 數據量比較小的時候,也不適合創建索引
?? ?3, 即使適合創建的地方,也不是越多越好;
?? ?
?? ?
> db.class.ensureIndex({name:1})
> db.class.getIndexes()
> db.class.dropIndex("name_1")
> db.class.dropIndex({name:1})
> db.class.dropIndexes()
> db.class.ensureIndex({name:1, age:1})
聚合: 對數據文檔進行整理統計
db.collectionName.aggregate()
功能: 聚合函數,配合聚合條件進行數據整理統計
參數: 聚合條件
聚合操作符:
$group ?分組操作,類似group by; 和分組操作符配合使用,按什么來分組;
+++++++++++++++++++++++++++++++++++++
分組操作符: 和$group配合
$sum 求和
-----------------------
統計每組個數:
> db.class.aggregate({$group:{_id:'$sex', num:{$sum:1}}})
---------------------------
$group 分組
$sex: 按照sex進行分組
$num: 分組后的域的名字key name
$sum: 求和
1 ?? ??? ?每統計一個數計為1
----------------------
統計每組年齡和
> db.class.aggregate({$group:{_id:'$sex', num:{$sum:'$age'}}})
------------------------
$avg:?? ?統計平均數
求平均年齡:
> db.class.aggregate({$group:{_id:'$sex', num:{$avg:'$age'}}})
------------------------
$min 分組完求各組的最小值
> db.class.aggregate({$group:{_id:'$sex', num:{$min:'$age'}}})
------------------------
$max: 分組完求各組最大值
> db.class.aggregate({$group:{_id:'$sex', num:{$max:'$age'}}})
------------------------
$first 返回每組文檔第一個指定域值
> db.class.aggregate({$group:{_id:'$sex', num:{$first:'$age'}}})
------------------------
$last: ?? ?返回每組文檔最后一個指定值
> db.class.aggregate({$group:{_id:'$sex', num:{$last:'$age'}}})
+++++++++++++++++++++++++++++++++++++
$project?? ?用于修飾文檔的顯示結構,規則類似find()的第二個參數
> db.class.aggregate({$project:{_id:0, name:1,age:1}})
> db.class.aggregate({$project:{_id:0, Name:'$name', Age:'$age'}})
$match?? ?過濾數據, 相當于find中的第一個參數query
> db.class.aggregate({$match:{sex:'female'}})
> db.class.aggregate({$match:{age:{$gt:10}}})
$skip 跳過前幾條文檔
> db.class.aggregate({$skip:5})
$limit?? ?顯示幾條文檔
> db.class.aggregate({$limit:2})
$sort 排序
> db.class.aggregate({$sort:{age:1}})
聚合管道: 將前一個操作的結果給下一個聚合操作繼續執行
db.collectionName.aggregate([聚合1,聚合2, 聚合3...])
> db.class.aggregate([{$match:{age:{$gt:10}}},{$limit:3},{$sort:{age:1}}])
聚合練習:
使用grade數據庫,?
增加分數域 score:{'chinese':38, 'englist':78, 'math':98}
1, 按照性別分組統計每組人數
?? ?> db.class.aggregate({$group:{_id:'$sex', count:{$sum:1}}})
2, 按照姓名分組,過濾出有重名的同學
?? ?> db.class.aggregate([{$group:{_id:'$name', count:{$sum:1}}},{$match:{count:{$gt:1}}}, {$project:{_id:1}}])
3, 按照每名男生的語文成績分組
?? ?> db.class.aggregate([{$match:{sex:'m'}},{$group:{_id:'$score.chinese'}}])
?? ?
4, 將女生按照英語成績分數降序排列
> db.class.aggregate([{$match:{sex:{$in:['f','female']}}}, {$project:{_id:0,name:1,sex:1,english_Score:'$score.englist'}}, {$sort:{english_Score:-1}}])
**************************************************
固定集合,?
定義:mongo中可以創建大小固定的集合,稱為固定集合; 固定集合的性能出色,適用于很多場景;
特點: 插入速度快
?? ??? ?順序查詢速度快
?? ??? ?能夠淘汰早期數據
?? ??? ?可以控制集合空間
場景:可以輪轉更新,緩存, 日志存儲等等;?
?? ??? ?
db.createCollection(collectionName, {capped:true,size:100, max:1000})
collectionName: 固定集合名字
size: 設置固定集合大小,kb
max :最多能容納多少條文檔
文件存儲:
數據庫存儲文件的方式:
1, 在數據庫中以字符串的方式存儲文件在本地的路徑
?? ?優點: 解約DB空間
?? ?缺點: 當DB或者文件位置發生變化,即需要更新文檔內容
2, 將文件以二進制方式存儲在數據庫中
?? ?
mongo中,使用GridFS方法 進行大文件存儲
GridFS: 是mongodb中大文件存儲的一種方案,大于16M的文件為大文件;
在mongodb中,創建兩個集合,共同完成對文件的存儲
fs.files: 存儲文件的基本信息:如文件名,文件類型,文件大小等
fs.chunks: 實際存儲文件的內容,以二進制方式分塊存儲;將大文件分為多個小塊,每塊占一個chunk
mongofiles -d dbname put filename 文件存儲
mongofiles -d gridfs get english.mp3 :文件提取
相同文件的fs.files和fs.chunks 通過相同_id來進行關聯
> db.fs.files.find({},{_id:0})
{ "chunkSize" : 261120, "uploadDate" : ISODate("2019-06-23T11:57:08.963Z"), "length" : 20599159, "md5" : "13c794abcdc36e15c84055a1fc87832b", "filename" : "english.mp3" }
{ "chunkSize" : 261120, "uploadDate" : ISODate("2019-06-23T12:11:14.631Z"), "length" : 20599159, "md5" : "13c794abcdc36e15c84055a1fc87832b", "filename" : "chinese.mp3" }
>
大文件存儲的優缺點:
優點:存儲方便,便于移植,沒有對文件個數限制
缺點: 讀寫效率低,占磁盤空間;
----------------------
python操作Mongo ---> mongodb編程接口:pymongo
安裝: sudo pip3 install pymongo
操作步驟:
1, 創建mongo數據庫的連接對象
?? ?conn = MongoClient('localhost',27017)?
2, 生成數據庫對象: stu庫
?? ?db = conn.stu
?? ?
3, 生成集合對象 table name: class0
?? ?my_set = db.class0
4, 增刪改查索引聚合操作
5, 關閉對象: conn.close()
插入數據:
insert()
insert_many()
insert_one()
save()
刪除數據:?
remove({}, multi = True) multi 默認True,pymongo中默認刪除所有符合條件的文檔;區別于mongo中的remove;
查找數據:?
find() ? 查找數據庫內容; 同mongo shell find()
?? ??? ?返回一迭代器;?
?? ??? ?
find_one() 只返回一條文檔
修改操作:
update()?? ??? ?操作和mongoshell 中相同
update_many()?? ?匹配到多個文檔時同時修改
update_one()?? ?只修改匹配到的第一條文檔
eg:
my_set.insert({name:'llj', gender:'female', age:18})
my_set.insert({name:'llj', gender:'female', age:18},{})
my_set.remove({name:'llj'}, muulti = False)
my_set.remove() 刪除所有文檔
cur = my_set.find({'gender':{'$exists':True}},{_id:0})
for i in cur:
?? ?print(i)
for i in cursor.skip(2).limit(3):
?? ??? ?print(i)
?? ??? ?
for i in cursor.sort([('name',1)])
?? ??? ?print(i)
編程中,mongo shell中的null 要用Python中的None替代
wrong: my_set.update_one({age:null},{name:'胤禛'})
right: my_set.update_one({age:None},{name:'胤禛'})
?? ?
?? ?
索引操作
創建單個索引
ensure_index('name')
復合索引創建:
index = my_set.ensure_index([('name',1),('age',-1)])
唯一索引:
index = my_set.ensure_index('field_name', unique = True)
稀疏索引:
index = my_set.ensure_index('name',sparse = True)
查看索引:
list_indexes(), 返回迭代器
for i in my_set.list_indexes()
?? ?print(i)
刪除索引:
drop_index(indexName) ?? ?刪除單個索引
drop_indexes()?? ?刪除所有索引
?? ?
?? ?
聚合操作
aggregate([])?? ??
參數與mongo shell中聚合參數寫法一致;
返回值: 迭代器,同find()返回值
l = [{'$group':{'_id':'$King', 'count':{'$sum':1}}}
?? ?{'$match':{'count':{'$gt':1}}}]
cursor = my_set.aggregate(l)
for i in cursor:
?? ?print(i)
grid.py
#用來獲取數據庫中gridfs的存儲文件
from pymongo import MongoClient
import gridfs
#創建連接對象
conn = MongoClient('localhost', 27017)
db = conn.grid
#獲取gridfs對象
fs = gridfs.GridFS(db)
#所有文件的游標
file = fs.find()
print(files)
print(files.count())
#代表各個文件的對象
for file in files:
?? ?if file.filename == 'abc.mp3':
?? ??? ?with open(file.filename, 'wb') as f:
?? ??? ??? ?while True:
?? ??? ??? ??? ?# file 的read()函數可以獲取文件內容
?? ??? ??? ??? ?data = file.read(64)
?? ??? ??? ??? ?if not data:
?? ??? ??? ??? ??? ?break
?? ??? ??? ??? ?f.write(data)
conn.close()
#save_img.py
#將圖片以二進制存儲到數據庫中
from pymongo import MongoClient
import bson.binary
conn = MongoClient('localhost',27017)
db = conn.file
my_set = db.img
#存儲
f = open('img.jpg', 'rb')
#將讀取的二進制流變為bson格式二進制的字串
content = bson.bianry.Binary(f.read())
my_set.insert({'filename':'img.jpg', 'data':content})
##提取文件
data = my_set.find_one('filename':'img.jpg')
#通過字典的方式獲取內容進行寫入即可
with open(data['filename', 'wb']) as f:
?? ?f.write(data['data'])
?? ?
?? ?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
