1. 程式人生 > >Python-MongoDB

Python-MongoDB

資料庫 MongoDB

程式  =  資料結構 + 演算法

數儲存的發展階段

檔案管理階段  
優點 : 資料可以長期儲存
        能儲存大量的資料
                使用比較簡單

缺點 : 資料的一致性差
        資料冗餘度大
                查詢修改不方便

資料庫管理階段

優點 : 資料組織結構化
        冗餘度小
容易擴充
查詢效率高
方便使用程式自動處理
缺點 : 需要使用sql語句等特定的語句處理,相對比較複雜

幾個概念:

資料: 能夠輸入到計算機中被識別處理的資訊集合

資料庫 :按照資料組織結構,儲存和管理資料的倉庫。是在資料庫管           理系統管理和控制下存放在一定介質上的資料集合。

資料庫管理系統:管理資料庫的軟體,用於建立使用和維護資料庫

資料庫系統:由資料庫,資料庫管理系統,開發工具等共同構成的集合             概念

關係型資料庫

採用關係模型來組織資料結構的資料庫

Oracle  DB2  SQLServer  MySql  SqLite(python標準庫支援)

優點 : 容易理解,類似我們常見的表格模型
        使用方便,都是通過sql語句進行操作,sql語句是非常成熟的
                易於維護,完整性好,資料一致性高,降低了冗餘
                技術成熟,可以使用外連線等比較複雜的操作

缺點 : 不能很好的滿足高併發的需求,每次操作需要sql語句需要解         析
針對海量資料的瞬間爆發在讀寫效能上顯得不足,關係型資料庫內部每一步操作為了保證原子型都會加鎖
資料一致性較高,在處理某些資料情況時浪費資源 
資料庫擴充套件比非關係型資料庫要複雜困難
            

非關係型資料庫 NoSQL (Not only sql)

優點 : 高併發,大資料下讀寫能力強
        支援分散式,容易擴充套件
                弱化了資料結構,降低了資料的一致性

缺點 : 沒有join等複雜的操作
通用性差 (不同的nosql資料庫有不同的使用方法)
操作靈活即容易混亂

面試要求 : 能夠描述關係型和非關係型資料庫特點

Nosql的使用情況:

1.資料模型簡單靈活,一致性差
2.對資料庫的併發處理要求高
3.資料庫設計時無法準確估量大小,後期可能需要擴充套件
4.給定的資料關係比較容易建立起鍵值模型

Nosql的分類

1.鍵值型資料庫
    Redis   oracle BDB   Tokyo

2.列儲存資料庫
    HBase  

3.文件型資料庫
    MongoDB  CouchDB

4 圖形資料庫

要求 : 知道Nosql資料庫分為幾類,Mongodb是文件型資料庫

MongoDB

1.是一個文件型非關係資料庫
2.由c++編寫的資料庫 
3. 支援豐富的查詢操作 
4.支援眾多程式語言的介面 (python  ruby  c++ c#  PHP)
5.使用方便,便於部署
6.資料格式豐富
7.支援分散式擴充套件

Mongodb安裝

自動安裝 

sudo  apt-get install mongodb  

預設安裝位置 /var/lib/mongodb
配置檔案   /etc/mongodb.conf
命令集  /usr/bin

手動安裝

1.下載對應系統的安裝包
www.mongodb.com   ---》 download  ---》community server
2. 選擇安裝目錄  (/user/local/  /opt)
選擇一個位置將安裝包解壓  tar 
3.進入解壓後的資料夾,將bin目錄新增到環境變數
PATH=$PATH:/usr/test/mongodb/bin/
export PATH
將這兩句新增到linux自動執行指令碼
/etc/rc.local   或者  /etc/bash.bashrc  或其他自啟動指令碼

4. 重啟系統 
reboot 
source /etc/bash.bashrc

5.設定資料庫的儲存位置
sudo mkdir -p  /data/db 
mongod  --dbpath  /data/db  

mongodb 埠號  27017  

設定Mongodb的埠號 
mongod --port  8888  

mongo 

mongo  shell  表示進入到mongodb的互動模式  注意:JavaScript


資料型別 :字串   整型  布林型  浮點型   陣列型別  時間型別
文件型別   空值null    字串(symbol 通常表示特殊字元)  
時間戳    ObjectID  二進位制   程式碼js   正則表示式

mongodb 儲存資料的一些概念

mysql        mongo        含義

database    database      資料庫

table       collection    表/集合

column      field         欄位/域

row         document      記錄/文件

index       index         索引  

------------------——---
id  |    name  |  age
-----------------------
1   |   Lily   |   17
-----------------------
2   |   Lucy   |   18
-----------------------
{
    "_id":ObjectId("askjdfhask12314klesaj"),
    "name":"Lily",
    "age" :17
,
{
    "_id":ObjectId("askas978fa89sfsdf09aj"),
    "name":"Lucy",
    "age" :18
}

進入mongo shell  :  mongo
退出mongo shell  :  quit()

建立資料庫

use databasename

e.g.  
建立一個叫stu的資料庫
use stu

* use實際的功能表示你選擇使用哪個資料庫,如果選擇一個不存在的資料庫則當向這個資料庫插入資料時,資料庫會自動建立

檢視當前資料庫系統中的資料庫

show  dbs

資料庫的命名規則:

1.原則上是滿足以下幾條的任意UTF-8格式的字串
2、不能是‘’字元
3、不能含有 空格' '   點'.'   ‘/’  '\'   '\0'
4. 習慣上全部小寫
5、不應超過64位元組
6. 不能使用admin   local   config 這三個名字

admin : 儲存使用者許可權
local : 不會被複制,只能用於本機操作 
config: 分片處理時儲存分片資訊

db  ————》一個數據庫全域性量 代表你當前正在使用的資料庫

db 預設表示 test資料庫

資料庫的備份和恢復

備份   mongodump  -h  dbhost -d dbname  -o  dbdir

e.g.  mongodump -h 127.0.0.1 -d stu -o student
      將本機stu資料庫備份到當前目錄下的student資料夾

恢復   mongorestore  -h  <hostname>:<port> -d dbname <path>

e.g.   mongorestore -h 127.0.0.1:27017 -d  test student/stu

資料庫的檢測

mongostat

insert(每秒插入次數) query(每秒查詢次數) update(每秒更新次數) delete(每秒刪除次數) getmore command(每秒執行命令次
數) dirty used flushes(每秒向磁碟寫入次數) vsize(使用虛擬記憶體情況)   res(使用實體記憶體情況) qrw arw net_in net_out conn
time

mongotop  檢測每個資料庫的讀寫時長

ns 資料表   total  read 讀時長  write 寫時長

刪除資料庫

db.dropDatabase()

建立集合

db.createCollection(collection_name)

檢視資料庫中的集合

show tables
或
show collections

集合的命名規則

1.不能是空字串
2.不能含有 ‘\0’
3. 不能以system.開頭,這是系統集合的保留字首
4.集合不要和保留字重名不要包含$

建立集合2 

當向一個集合中插入一條文件,如果這個集合不存在,則會自動建立
db.collection_name.insert()

e.g.    db.class2.insert({name:'Lily',age:17,sex:'w'})
會自動建立class2這個集合

刪除集合

db.collection_name.drop()

e.g.   db.stu.drop()
刪除stu這個集合

文件

在mongodb中資料的組建形式 
由鍵值組成,類似python中的字典 

mongodb中資料文件為bson格式 (類似於python字典,使用鍵值的方                               式儲存和展示資料)

文件中 鍵的命名規則

1.utf-8格式的字串
2.不能有\0  不能為空 (習慣上不用. 和 $)
3.以_開頭的很多都是保留的鍵,所以一般不用_開頭

注意: 文件中的鍵值對是有序的
       文件中的值指的就是文件支援的資料型別
             mongodb中區分大小寫

支援資料型別

整型       整數, 32位整型
布林       True  False 
浮點型      儲存小數
Arrays      列表陣列
Timestamp   時間戳
Date        時間日期
Object      內部文件
Null        空值
Symbol      特殊字元字串
Binary data  二進位制資料
code         程式碼
regex        正則表示式
ObjectId     ObjectId字串                          ObjectId("5ab9f98588ce659bcaa3a8ee")

objectid  : 系統自動為每個文件生成的不重複的主鍵
            鍵名稱>  _id
                    值    >  ObjectId("5ab9f98588ce659bcaa3a8ee")
24位十六進位制數  8 文件建立事件   6  機器ID  4程序ID  6 計數器 

集合設計原則

1. 同一類文件存在一個集合中
2. 集合中儘量儲存域和文件格式相近的文件
3. 集合中可以存在文件資料的差異

插入文件

db.collection_name.insert()
e.g.  db.class1.insert({'name':'寶強','age':22,'sex':'m'})

* 插入文件時域名可以不加引號
db.class1.find() 檢視

插入多條文件

db.collection_name.insert([{},{},{}....])

e.g.
db.class1.insert([{name:'阿哲',age:24},{name:'阿蓉',age:22,sex:'w'},{name:'阿花',age:18,sex:'w'}])

*_id為系統定義主鍵值,如果使用系統值則保證不重複,如果自定義值即會覆蓋系統值,但是自己也不能讓該域重複

save插入資料

db.collection_name.save()

e.g.  db.class1.save({_id:1,name:'沙師弟',age:1700})

如果不新增_id域的時候 同insert
如果新增_id域,該域值如果不存在則正常插入,如果存在則修改原資料

save不能夠插入多條文件

修改集合名稱

db.collection_name.renameCollection('newname')

e.g.  db.class1.renameCollection('class0')
將class1 改名為 class0

db.collection_name  《====》
db.getCollection('collection_name') 獲取表物件

e.g.   db.getCollection('class1').insert({name:'Lucy',age:18})

查詢

select ... from  tablename where ....

db.collection_name.find()  --> select * from tablename

find(query,field)
功能 : 查詢所有符合篩選要求的文件
引數 : query : 篩選條件  相當於where子句
                field : 展示的域  0 表示 不展示該域
                                   1 表示 展示該域

返回值:返回所有符合要求的文件

field :選擇要展示的域

1.  以鍵值對的形式給每個域賦值0,1表示是否要顯示該域
2.  如果給域設定為0 則其他域自動為1,如果給某個域設定為1,則其他的自動為0。兩者不能混用
3.  _id 比較特殊,預設為1,如果不想顯示則設定為0。_id為0時其他的域是可以為1的。
4. 如果不寫該引數,則表示顯示所有的域

e.g.   db.class1.find({},{_id:0,name:1,age:1})

query : 查詢年齡是22的人

1.以鍵值的方式確定查詢條件
2.如果不寫這個引數則表示查詢所有文件

e.g.  db.class0.find({age:22},{_id:0})  ===>
        select name,age,sex from class0 where age=22

db.collection_name.findOne()

功能 : 查詢符合條件的第一條文件
引數 : 同find 
返回值 : 返回查詢到的文件

e.g.   db.class0.findOne({age:22},{_id:0})

query 的更多用法

比較操作符

$eq  等於
db.class0.find({age:{$eq:22}},{_id:0})
等價於db.class0.find({age:22},{_id:0})

*比較運算子也是用鍵值的方式,給比較運算子設定一個值,表示相應的關係

$lt  小於   <

e.g.  db.class0.find({age:{$lt:22}},{_id:0})
* 在mongo中字串也可以比較大小

$lte  小於等於  <=
e.g.  db.class0.find({age:{$lte:22}},{_id:0})

$gt   大於  >

db.class0.find({age:{$gt:22}},{_id:0})

$gte  大於等於  >=

db.class0.find({age:{$gte:22}},{_id:0})

$ne  不等於  != 

db.class0.find({age:{$ne:22}},{_id:0})

*如果某個文件沒有age這個域也會顯示為不等於22 

$in  包含    

db.class0.find({age:{$in:[22,23,24]}},{_id:0})
找出年齡為22   23   24的文件

$nin  不包含

db.class0.find({age:{$nin:[22,23]}},{_id:0})

邏輯操作符

$and   邏輯與

1. 預設在query中逗號分割的多個條件即為邏輯與關係

db.class0.find({age:22,sex:'m'},{_id:0})
等價
db.class0.find({$and:[{age:22},{sex:'m'}]},{_id:0})

e.g.  年齡在 20 --- 25 之間的
db.class0.find({age:{$gt:20,$lt:25}},{_id:0})

$or 邏輯或

db.class0.find({$or:[{age:22},{sex:'w'}]},{_id:0})

年齡小於20或者大於25的
db.class0.find({$or:[{age:{$lt:20}},{age:{$gt:25}}]},{_id:0})

$not  邏輯非

db.class0.find({age:{$not:{$eq:22}}},{_id:0})

$nor  既不也不  (集合中的條件都不滿足的文件)

db.class0.find({$nor:[{age:18},{sex:'m'}]},{_id:0})

條件混合

年齡 小於 20  或者  姓名為  阿蓉  並且性別為 女的人

< 20 or (name = '阿蓉' and  sex = 'w')

db.class0.find({$or:[{age:{$lt:20}},{name:'阿蓉',sex:'w'}]},{_id:0})

陣列查詢

檢視hobby陣列中含有Python的文件
 db.class1.find({hobby:'Python'},{_id:0})

$all

查詢陣列中包含多項的文件
 db.class1.find({hobby:{$all:['Python','Game']}},{_id:0})

$size 
查詢陣列中項數為指定個數的文件

e.g.  db.class1.find({hobby:{$size:2}},{_id:0})

第二個引數中
$slice  
顯示陣列中的前幾項

e.g.  顯示陣列前一項
db.class1.find({},{_id:0,hobby:{$slice:1}})
跳過第一項顯示後面兩項
db.class1.find({},{_id:0,hobby:{$slice:[1,2]}})

其他查詢方法 :

$exists  
判斷一個域是否存在

查詢存在 sex 域的文件
db.class0.find({sex:{$exists:true}},{_id:0})
查詢不存在 sex 域的文件
db.class0.find({sex:{$exists:false}},{_id:0})

$mod   
通過整除餘數進行查詢
  
            查詢 age 值被3除餘數為0的文件
e.g.  db.class0.find({age:{$mod:[3,0]}},{_id:0})

$type 
查詢值為指定資料型別的文件

https://docs.mongodb.com/manual/reference/operator/query/type/

查詢age域的值資料型別為1 的文件
db.class0.find({age:{$type:1}},{_id:0})

和查詢結果相關的幾個函式

distinct() 
功能 : 檢視一個集合中某個域的值所覆蓋的範圍

檢視class0集合中文件 age域都包含哪些值 ,也可以檢視一個列表域
則將列表值整合
e.g. db.class0.distinct('age')

pretty()
功能 : 將查詢結果格式化顯示

e.g.   db.class0.find({}).pretty()

limit(n)
功能 : 查詢結果顯示前n個文件

顯示查詢結果的前三條文件

db.class0.find({},{_id:0}).limit(3)

skip(n)

功能 : 跳過前n條文件進行顯示

跳過前2條文件進行顯示
db.class0.find({},{_id:0}).skip(2)

count()

功能:對查詢結果進行計數

統計age為22的文件個數
db.class0.find({age:22},{_id:0}).count()

sort()

功能:按照指定的欄位進行排序 
引數: 鍵值對  某個域按照升序排序則值為1 降序則值為-1

e.g.   查詢結果按照age降序進行排序
 db.class0.find({},{_id:0}).sort({age:-1})

複合排序:當第一個排序項相同的時候,使用第二個排序項進行排序

 db.class0.find({},{_id:0}).sort({age:1,name:-1})

函式的聯合使用

獲取年齡最小的三個文件

db.class0.find({},{_id:0}).sort({age:1}).limit(3)

刪除文件

db.collection_name.remove(query,justOne)
功能 : 刪除文件
引數 : query : 定位要刪除的文件資料  類似 sql where子句
                 用法和查詢相同
            
                justOne : 給bool值  預設 false 表示刪除所有符合條件的資料文件
                           如果賦值為true 則表示只刪除第一條符合條件的文件

e.g.   
刪除所有不包含sex域的文件
db.class0.remove({sex:{$exists:false}})
刪除age為22的文件中的第一條
db.class0.remove({age:22},true)

刪除集合中所有的文件
db.collection_name.remove({})

更新文件

update  tablename set .... where ....

db.collection_name.update(query,update,upsert,multi)
功能 : 更新一個文件資料
引數 :query : 定位要更新的資料 相當於where 用法同查詢
         
             update : 將資料更新為什麼  相當於set 需要配合修改器操          作符來使用
        
             upsert : bool值 預設為false 表示當定位的文件不存在則           無法修改。 如果設定為true ,表示如果定位的文      
檔不存在則插入這條文件
        
                multi  : bool值 預設為false 如果query匹配的文件有多           條則只修改第一條。如果設定為true,則修改所     
有匹配到的文件


e.g.
修改阿花的年齡為19
db.class0.update({name:'阿花'},{$set:{age:19}},false)

如果query不存在則根據query 和 update兩個引數插入一個文件
db.class0.update({name:'阿哲'},{$set:{age:20}},true)

multi 為false
當age為22的有多個文件時只修改第一個
db.class0.update({age:22},{$set:{age:18}},true,false)

multi 為true
修改所有sex = ‘w’ 的文件  age為20 
db.class0.update({sex:'w'},{$set:{age:20}},true,true)

update

修改器 : 將資料修改為什麼

$set
修改一個值

e.g.  修改阿花 年齡21  性別 m
db.class0.update({name:'阿花'},{$set:{age:21,sex:'m'}})

* set 同時有增加一個域的作用

$unset
刪除一個域

e.g.  
刪除阿哲的 age域  (age: 後面什麼數字都是刪除習慣寫1)
db.class0.update({name:'阿哲'},{$unset:{age:0}})

$rename 
修改一個域的名稱

e.g. 將所有文件中sex域名修改為gender
db.class0.update({},{$rename:{sex:'gender'}},false,true)


$inc  
對某個域的值進行加減修改

e.g.  給姓名為寶強的文件age增加1  (如果值為負數即為減少)
 db.class0.update({name:'寶強'},{$inc:{age:1}})
 db.class0.update({name:'阿蓉'},{$inc:{age:-2}})

$mul 
對某個域的值進行乘法修改

e.g.  給age域的值進行乘法運算
db.class0.update({name:'阿蓉'},{$mul:{age:2}})
db.class0.update({name:'阿蓉'},{$mul:{age:0.5}})

$min   
設定最小值,如果query到的文件指定域值小於 min設定則不做修改,如果大於指定min值則改為min值

e.g.  如果寶強的年齡小於16則不變,大於16則改為16
db.class0.update({name:'寶強'},{$min:{age:16}})

$max
設定最大值, 如果query到的文件指定的域值大於max設定值則不變,如果小於max給出的值則修改為max值

將所有年齡不到17的文件年齡修改為17
db.class0.update({},{$max:{age:17}},false,true)

修改器可以一起使用

e.g.   將阿花年齡增加2  性別修改為w 
db.class0.update({name:'阿花'},{$inc:{age:2},$set:{gender:'w'}})

陣列修改器

$push  向陣列中新增一項
db.class1.update({name:'Lucy'},{$push:{hobby:'Computer'}})

$pushAll  向陣列中增加多項元素

db.class1.update({name:'Lily'},{$pushAll:{hobby:['Python','html']}})

$each  

db.class1.update({name:'Tom'},{$push:{hobby:{$each:['chui','kan']}}})

$pull 從陣列中刪除一個元素
db.class1.update({name:'Tom'},{$pull:{hobby:'chui'}})

$pullAll  從陣列中刪除多個元素

db.class1.update({name:'Tom'},{$pullAll:{hobby:['gongfu','kan']}})

$pop  從陣列的兩端彈出元素

彈出陣列中最後一項  1
db.class1.update({name:'Lucy'},{$pop:{hobby:1}})

彈出陣列中的第一項  -1
db.class1.update({name:'Jame'},{$pop:{hobby:-1}})

$addToSet   向陣列中新增一個元素,該元素不能和其他元素重複

如果hobby中已經有Game則無法新增 (但是使用push是可以的)
db.class1.update({name:'Jame'},{$addToSet:{hobby:'Game'}})

null

1. 某個域如果沒有值卻存在則可以設定為null 
2. 表示某個域不存在也能夠進行匹配

e.g. 
 db.class2.find({country:null})

文件型別資料

*外部文件的域引用內部文件的域通過.的方法逐層引用,在使用時需要加引號

查詢內部文件 title值為 Python web 的文件   
db.book.find({'Python.title':'Python web'})

db.book.update({'Python.title':"Python web"},{$set:{'Python.price':40.8}})

陣列資料的下標引用

使用陣列的域點引用下標的方式可以表示陣列中具體某一項

db.class1.find({'hobby.0':'song'})
db.class1.update({name:'Lucy'},{$set:{'hobby.1':'畫畫'}})

文件有序性的體現

通過[]的方式即可以取得查詢結果中的第幾項
db.class1.find({},{_id:0})[2] 

索引 : 指的是建立指定鍵值及所在文件中的儲存位置對照關係清單。使用索引可以方便我們快速查詢,減少遍歷次數,提高效率。

建立索引 : 
ensureIndex()
功能 : 建立索引
引數 : 提供索引的類別選項

* 1 表示為該域建立正向索引,-1表示逆向索引

根據name域建立索引

db.class0.ensureIndex({'name':1})

檢視當前集合的索引
db.class0.getIndexes()

* 系統自動為_id 建立了索引

建立複合索引 (同時根據多個域建立索引)

db.class1.ensureIndex({'name':1,age:1})

刪除索引

db.collection_name.dropIndex()
功能:刪除一個索引
引數:索引的名稱

* _id 索引不能被刪除

db.class0.dropIndex({name:1})   
db.class1.dropIndex({name:1,age:1})   將複合索引刪除

刪除所有索引

db.collection_name.dropIndexes() 
功能 : 刪除指定集合中除_id外的所有索引

e.g.  刪除class1中的所有索引
db.class1.dropIndexes()

explain() : 顯示詳細的查詢操作資訊

e.g. 
db.class0.find({name:'阿蓉'},{_id:0}).explain()

索引型別

陣列索引: 如果對某個陣列域建立索引,則對陣列中的每個值均建立了索引。 通過陣列中單個值查詢也會提高效率

db.class1.find({hobby:'run'},{_id:0}).explain()

子文件索引

某個域值為文件,對其子文當建立索引,則加快通過子文件進行查詢的查詢速度

db.class1.ensureIndex({'Python.price':1})

唯一索引

唯一索引建立時希望建立索引的域有不同的值,也可以通過這個方法來限制域的值

db.class0.ensureIndex({name:1},{'unique':true})

建立索引時指定域的值不能有重複,建立後插入也不允許插入重複的值

覆蓋索引

查詢時,只獲取索引項的內容,而不去連線其他文件內容。這樣從索引表就可以得到查詢結果,提高了查詢效率

索引為name查詢項也為name
db.class0.find({name:'寶強'},{_id:0,name:1})

稀疏索引(間隙索引)

只針對有指定域的文件建立索引表,沒有該域的文件不插入到索引表中

對age建立稀疏索引
db.class0.ensureIndex({age:1},{sparse:true})

文字索引

使用文字索引可以快速進行文字檢索,這在較長的字串搜尋中比較有用

1.建立文字索引

db.class2.ensureIndex({msg:'text',description:'text'})

2. 通過單詞進行索引搜尋 (多個單詞用空格隔開,如果有其中任意一個單詞就會被搜尋)

db.class2.find({$text:{$search:"old beautiful"}},{_id:0})

3. 搜尋包含空格的語句 要用轉義字元

db.class2.find({$text:{$search:"\"city is\""}},{_id:0})

4. 搜尋某個單詞, 並且不包含某個單詞

db.class2.find({$text:{$search:"city -big"}},{_id:0})

刪除文字索引

通過 getIndexes()檢視索引名稱
通過 dropIndex() 刪除 

e.g.
db.class2.dropIndex('msg_text_description_text')

索引約束

1、 影響插入 刪除  修改資料的效率。當資料發生修改是,索引必須同步更新。
2、 索引也佔有一定的空間,所以當資料量比較小時不適宜建立索引

綜上: 並不是所有情況下都適合建立索引或者建立大量索引

固定集合

mongodb中可以建立大小固定的集合,稱之為固定集合,固定集合效能出色且適用於很多場景
比如 : 日誌處理, 臨時快取 

特點 : 插入輸入快
            順序查詢速度快
            能夠淘汰早期的資料

建立固定集合

db.createCollection(collectionname,{capped:true,size:10000,max:1000})

size : 表示設定的固定集合的大小  單位 kb 
max  : 表示固定集合中最多存放多少條文件 

e.g.
db.createCollection('log',{capped:true,size:1000,max:3})

聚合

對資料文件進行整理統計

db.collection_name.aggregate()
功能 : 聚合函式,配合聚合條件進行資料整理

聚合操作符

$group   分組  按照什麼分組由具體的分組操作符而定

db.class0.aggregate({$group:{_id:'$gender', num:{$sum:1}}}) 
           聚合統計   分組   按照哪個域分組  統計結果域名    

$sum  求和

db.class0.aggregate({$group:{_id:'$gender',num:{$sum:'$age'}}})

$avg  求平均數

db.class0.aggregate({$group:{_id:'$gender',num:{$avg:'$age'}}})

$min  求最小值

db.class0.aggregate({$group:{_id:'$gender',num:{$min:'$age'}}})

$max  求最大值

db.class0.aggregate({$group:{_id:'$gender',num:{$max:'$age'}}})

$first  第一個文件的指定值

db.class0.aggregate({$group:{_id:'$gender',name:{$first:'$name'}}})

$last   最後一個文件的指定值

db.class0.aggregate({$group:{_id:'$gender',name:{$last:'$name'}}})


$project  用於修飾文件的顯示結構 

值同find的第二個引數相同

可以改變顯示的域名
db.class0.aggregate({$project:{_id:0,Name:'$name',Age:'$age'}})

$match  過濾資料

值和 query 部分一樣
db.class0.aggregate({$match:{age:{$lt:20}}})

$limit  顯示前幾條資料

值為一個正數
db.class0.aggregate({$limit:3})

$skip  跳過幾條資料

值為一個正數
db.class0.aggregate({$skip:2})

$sort   排序 

值同sort函式

db.class0.aggregate({$sort:{age:1}})

聚合管道

前一個聚合操作的結果給後一個聚合操作執行

格式 : 將多個聚合操作放到一個 [] 中

match 結果 ---- 》 sort 排序 ---》 project顯示

db.class0.aggregate([{$match:{gender:'m'}},{$sort:{age:1}},{$project:{_id:0}}])

GridFS 大檔案儲存

檔案的資料庫儲存
1. 在資料庫中以字串的方式儲存檔案在本地的路徑
優點:節省資料庫空間
缺點: 當資料庫或者檔案位置發生變化時即無法找到檔案

2. 將檔案以二進位制資料的方式儲存在資料庫中
優點 : 檔案和資料庫繫結 
缺點 : 當儲存檔案大時,空間使用大,提取困難

GridFS  : 是mongodb當中儲存大檔案的一種方案,mongodb中認為超過16M的檔案為大檔案

將檔案儲存在mongodb資料庫中,通過兩個集合共同完成該檔案的儲存

fs.files  : 儲存檔案的相關資訊 比如 檔名filename  檔案型別                          content_type 等

fs.chunks : 實際儲存檔案內容  以二進位制方式分塊儲存。 將大檔案分成多個小塊,每個小塊佔一條文件

mongofiles -d   dbname  put filename 
          
dbname: 檔案要儲存的資料庫,如果不存在則自動建立
filename : 要儲存的檔案

e.g.
mongofiles -d  grid  put abc.mp3

.檢視檔案資訊

db.fs.files.find()

檢視具體檔案內容

db.fs.chunks.find({files_id:ObjectId("xxxxx")})

fs.chunks 的域 _id 
               files_id  : 值為對應檔案在 fs.files 集合中的             文件的_id值
n  分塊資訊
data   具體檔案內容
優缺點 : 
優點 : 儲存方便    沒有檔案個數限制  方便移植
缺點 : 讀寫效率低  只能整體修改不能分塊更新

遊標

為什麼使用遊標
1.防止網路擁塞,造成資料傳輸滿
2.避免使用者解析帶來的體驗差,可以進行後端解析 

使用方法

var cursor = db.class0.find()  建立遊標cursor
cursor.hasNext()  檢視是否有下一條文件
cursor.next()    獲取下一條文件內容

通過python 操作mongodb資料庫

資料庫操作介面  pymongo

安裝
sudo pip3 install pymongo 

建立mongo的連線物件
conn = MongoClient('localhost',27017)

選擇要連線的資料庫
db = conn.stu 

選擇要連結的集合
my_set = db.class0

增  
insert()  insert_many()  insert_one()  
save()

刪 
remove()
功能:刪除一個文件
引數 : 可以通過query條件刪除
        可以通過文件的_id值進行刪除


查

find()
功能 : 查詢資料庫內容
引數 : 同mongoshell 中find函式引數 需要符合python語法
返回值 : 可迭代的遊標物件 ,通過for迴圈取值

遊標物件屬性函式
next() 取下一個文件
limit()  顯示多少文件
skip()  條多多少條文件
sort()  排序
count()  統計


說明 : 在python中支援mongodb 所有的操作符, 只是在使用的時候需要通過引號變為字串的形式

e.g.    find({'age':{'$gt':20}})
            find({'$or':[{'name':'zhang'},{'age':{'$lt':20}}]})

$lt $gt  $lte  $gte  $in $nin  $and $or $nor $ne

find_one() 
用法同find  返回值為查詢到的一個文件轉變的字典


改 
update()
同 mongo  shell 中update操作

update_many()
當匹配到多個文件時全部修改

update_one() 
只能修改第一條匹配到的文件

索引

ensure_index()

建立單一索引
index = my_set.ensure_index(name)

建立複合索引 1 表示升序  -1表示降序
index = my_set.ensure_index([('name',1),('King',1)])

create_indexes() 
功能 : 建立多個索引

1.建立索引條件物件 from  pymongo import IndexModel
index1 = IndexModel([('name',1),('King',-1)])
index2 = IndexModel([('king_name',1)])

2.將索引物件使用create_indexes生成索引
indexes = my_set.create_indexes([index1,index2])

list_indexes()     ------》mongoshell   getIndexes()
功能:檢視指定集合中的索引
引數
返回值 : 迭代物件,每個值為一個索引資訊

刪除索引

drop_index() 
功能 : 刪除一個索引
引數 : 索引的名稱

drop_indexes()
功能 : 刪除指定集合中所有索引

聚合

aggregate([])
功能 : 實現mongo的聚合操作
引數 : mongo  shell中聚合函式的引數一致 在使用聚合操作符時         用引號變為字串即可
返回值 : 迭代物件 同 find的返回值型別