Python全棧MongoDB資料庫(聚合、二進位制、GridFS、pymongo模組)

巴黎香榭發表於2018-08-23
斷網了2天  今天補上
聚合操作:
對文件的資訊進行整理統計的操作
返回:統計後的文件集合
db.collection.aggregate()
功能:聚合函式,完成聚合操作
引數:聚合條件,配合聚合操作符使用
返回:聚合後的結果

常用聚合操作符:
1.$group  分組聚合   要配合具體的統計操作符獲取結果
$sum  求和
db.class1.aggregate({$group:{_id:`$gender`,num:{$sum:1}}})
     分組   按照gender值統計 統計結果,求和每有一個加1
統計所有男生和女生的年齡之和
db.class1.aggregate({$group:{_id:`$gender`,num:{$sum:`$age`}}})
$avg  平均值
求男生 女生年齡的平均數
db.class1.aggregate({$group:{_id:`$gender`,num:{$avg:`$age`}}})
$max 求最大值
求男生女生的年齡最大值
db.class1.aggregate({$group:{_id:`$gender`,num:{$max:`$age`}}})
$min  求最小值
求男生女生的年齡最小值
db.class1.aggregate({$group:{_id:`$gender`,num:{$min:`$age`}}})
2.$project
用於修改文件的顯示效果
$project值的用法同find()的field引數相同
db.class1.aggregate({$project:{_id:0,name:1,age:1}})
自定義顯示的域名
db.class1.aggregate({$project:{_id:0,Name:`$name`,Age:`$age`}})
3.$match
過濾想要的資料
過濾年齡大於30的資料,$match值的寫法同query
db.class1.aggregate({$match:{age:{$gt:30}}})
4.$limit
顯示前幾個文件
db.class1.aggregate({$limit:3})
5.$skip
跳過前幾個文件顯示
db.class1.aggregate({$skip:2})
6.$sort   排序
按照年齡排序
db.class1.aggregate({$sort:{age:1}})

聚合管道
將前一個聚合操作產生的結果,交給後一個聚合操作繼續使用
db.collection.aggregate([{聚合1},{聚合2},{}…])
$match –> $sort –>$project
db.class1.aggregate([{$match:{gender:`m`}},{$sort:{age:1}},{$project:{_id:0}}])
聚合示例
使用grade資料庫
給更多同學新增 域score
score:{english:87,chinese:76,math:91}
1. 按照性別統計每組人數
aggregate({$group:{_id:`$sex`,num:{$sum:1}}})
2. 統計該班中有哪個同學姓名為重名同學
aggregate([{$group:{_id:`$name`,num:{$sum:1}}},{$match:{num:{$gt:1}}}])
3. 統計所有男生的語文成績,只列印姓名,性別,語文成績即可
aggregate([{$match:{sex:`m`}},{$project:{_id:0,name:1,sex:1,`score.chinese`:1}}])
4. 將所有女生按照英語成績降序排序
aggregate([{$match:{sex:`w`}},{$sort:{`score.english`:-1}}])
檔案儲存:
1.儲存路徑
將檔案放在本地路徑(網路路徑)下,然後資料庫中儲存該檔案的查詢路徑
  
優點 : 節省資料庫空間
缺點 : 當資料或者檔案位置發生變化時檔案即丟失
2. 將檔案轉換為二進位制,儲存檔案本身
資料庫支援二進位制資料格式
將檔案轉換為二進位制格式,然後存入資料庫中
優點 : 資料庫和檔案繫結,資料庫檔案即在
缺點 : 佔用資料庫空間大,存取效率低
mongodb儲存檔案本身
* 如果是小檔案建議轉換二進位制直接插入
* 如果是大檔案建議使用GridFS方案儲存(大於16M)
GridFS方案解釋
1. 在mongodb一個資料庫中使用兩個集合配合儲存檔案
2. fs.files 用來儲存檔案的相關資訊,為每一個檔案建立一個文件,
   儲存檔案,檔案大小,存入時間。。。
3. fs.chunks 用來分塊儲存檔案的實際內容(Binary data 型別資料)
儲存方法:
mongofiles  -d dbname(資料庫)   put  file(要儲存的檔案)
                                         
* 資料庫不存在會自動建立資料庫
  資料庫中會自動建立fs.files  fs.chunks兩個集合
fs.files文件結構:
{
“_id” : ObjectId(“5b7cdcd769d72e12b4f166d0”),
“chunkSize” : 261120,
“uploadDate” : ISODate(“2018-08-22T03:47:35.381Z”),
“length” : 305033,
“md5” : “3698b5e762b5b396766aaf9feef7e10d”, 
“filename” : “file.jpg”
}
fs.chunks文件結構
{
“_id” : ObjectId(“5b7cdcd769d72e12b4f166d2”),
“files_id” : ObjectId(“5b7cdcd769d72e12b4f166d0”), 
“n” : 1, 
“data” : BinData(0,”tQWR0AR……AG”) 
}
* 同一個檔案fs.files中的_id值等於fs.chunks中的    files_id域的值
提取方法:
mongofiles  -d  dbname   get  file
GridFS方案:
優點 : 儲存方便,提供較好的命令支援和程式設計介面
缺點 :  存取效率低下 還沒有複製的快
mongo shell中獲取遊標
* mongo shell下支援JS程式碼,可以通過JS獲取遊標,進而獲取資料操作結果。
var cursor = db.class1.find()
cursor.next()   獲取下一條結果
cursor.hasNext()  檢視是否有下一個物件
通過python操作 MongoDB:
pymongo 模組   第三方模組
安裝:
sudo  pip3 install  pymongo
操作步驟:
    1. 連線資料庫,生成資料庫連線物件
        conn = pymongo.MongoClient(`localhost`,27017)
    2. 選擇要操作的資料庫,生成資料庫物件 (__setitem__)
        db = conn.stu
        db = conn[`stu`]
    3. 獲取集合物件
        myset = db.class0
        myset = db[`class0`]
    4. 通過集合物件呼叫mongodb資料庫操作函式
        增刪改查,聚合,索引。。。。。
    5. 關閉資料庫連線
           conn.close()

插入文件:
insert()    插入資料 功能同 mongoshell
insert_many()  插入多條
insert_one() 插入一條
save()  插入資料,通過_id可以修改
查詢操作:
find()
功能 : 對資料庫進行查詢
引數 : 同mongoshell  find()
返回值 : 返回遊標物件
                cursor = myset.find({},{`_id`:0})
cursor的屬性函式
next()
limit()
skip()
count()
sort()
Python中sort和MongoDB的區別
                並且Python中的資料是字典和MongoDB的資料不同 
                所以鍵和操作符號都必須要加引號
pymongo  : sort([(`age`,-1),(`name`,1)])
mongoshell : sort({age:-1,name:1})
* 如果通過for或者next操作了遊標物件,再呼叫limit,skip,sort會報錯
find_one()
用法同mongoshell中 findOne()
返回一個字典
修改操作:
update(query,update,upsert = False,multi = False)
update_many()
update_one()
刪除操作:
remove(query,multi = True)
功能: 刪除文件
引數: query 篩選條件
       multi  預設True表示刪除所有符合條件的
              False只刪除一條
索引操作:
ensure_index()  建立索引
list_indexes()  檢視索引
drop_index()  刪除一個索引
drop_indexes() 刪除所有索引
聚合操作:
aggregate([])
引數和mongoshell一樣
返回值和find()函式一樣也是得到一個遊標物件
pymongo進行檔案存取操作:
GridFS 檔案提取:
import  gridfs
1. 連線資料庫,獲取相應的資料庫物件
2. 通過 gridfs.GridFS(db) 獲取集合物件(代表儲存檔案的兩個集合)
3. 通過find()查詢檔案返回遊標
4. 通過迴圈遍歷遊標獲取指定檔案物件,read()讀取檔案內容寫入本地
以二進位制的方式存取檔案
import bson.binary
增刪改查操作:
from pymongo import MongoClient 

#建立連線
conn = MongoClient(`localhost`,27017)

#建立資料庫物件
db = conn.stu 

#建立集合物件
myset = db.class4 

print(dir(myset))

# 插入操作
myset.insert({`name`:`張鐵林`,`King`:`乾隆`})
myset.insert([{`name`:`張國立`,`King`:`康熙`},
    {`name`:`陳道明`,`King`:`康熙`}])
myset.insert_many([{`name`:`唐國強`,`King`:`雍正`},
    {`name`:`陳建斌`,`King`:`雍正`}])
myset.insert_one({`name`:`鄭少秋`,`King`:`乾隆`})
myset.save({`_id`:1,`name`:`聶遠`,`King`:`乾隆`}) 

# 查詢操作

cursor = myset.find({},{`_id`:0})

# i為每個文件對應的字典
for i in cursor:
    print(i[`name`],`--->`,i[`King`])

myset = db.class1 
# 操作符使用引號變為字串
cursor = myset.find({`age`:{`$gt`:30}},{`_id`:0})

cursor.limit(2)#獲取前兩個文件
cursor.skip(2) #跳過前兩個
cursor.sort([(`age`,-1),(`name`,1)]) #對遊標內容排序

for i in cursor:
    print(i)
print(cursor.next()) #獲取下一個文件


dic = {`$or`:[{`age`:{`$gt`:35}},{`gender`:`w`}]}
data = myset.find_one(dic,{`_id`:0})
print(data)

# 修改操作
myset.update({`name`:`張國立`},
    {`$set`:{`king_name`:`玄燁`}})

myset.update({`name`:`霍建華`},{`$set`:{`King`:`乾隆`}},
    upsert = True)

myset.update({`King`:`乾隆`},
    {`$set`:{`king_name`:`弘曆`}},multi = True)

myset.update_one({`King`:`康熙`},
    {`$set`:{`king_name`:`愛新覺羅玄燁`}})

myset.update_many({`King`:`雍正`},
    {`$set`:{`king_name`:`胤禛`}})

# 刪除操作

myset.remove({`King`:`康熙`})
myset.remove({`King`:`乾隆`},multi = False)

#查詢並刪除
print(myset.find_one_and_delete({`King`:`乾隆`}))


#關閉連線
conn.close()
索引操作:

from pymongo import MongoClient 

#建立連線
conn = MongoClient(`localhost`,27017)

#建立資料庫物件
db = conn[`stu`] 

myset = db[`class1`] 

# 刪除所有索引
myset.drop_indexes()

# 建立索引
index = myset.ensure_index(`name`)
# 建立複合索引
index = myset.ensure_index([(`name`,-1),(`age`,1)])
print(index)

# 刪除一個索引
myset.drop_index(`name_1`)

# 建立特殊索引
index = myset.ensure_index(`name`,name = "myIndex",
    unique = True,sparse = True)

# 檢視集合中的索引
for i in myset.list_indexes():
    print(i)

myset = db.class4 

l = [
    {`$group`:{`_id`:`$King`,`num`:{`$sum`:1}}},
    {`$match`:{`num`:{`$gt`:1}}}
]

cursor = myset.aggregate(l)
for i in cursor:
    print(i)

conn.close()

檔案的存取:

from pymongo import MongoClient 
import bson.binary 

conn = MongoClient(`localhost`,27017)
db = conn.images 
myset = db.img 

#儲存
f = open(`file.jpg`,`rb`)

#轉換為mongodb的二進位制資料儲存形式
content = bson.binary.Binary(f.read())

#插入到資料庫
myset.insert({`filename`:`file.jpg`,`data`:content})

#提取

data = myset.find_one({`filename`:`file.jpg`})

#通過字典獲取到資料庫內容寫入本地
with open(data[`filename`],`wb`) as f:
    f.write(data[`data`])

conn.close()


手動存入檔案MongoDB預設建立的檔案資料匯出:
from pymongo import MongoClient 
#pymongo繫結的模組
import gridfs

conn = MongoClient(`localhost`,27017)
db = conn.grid 

#獲取gridfs物件
#fs綜合了fs.files  fs.chunks兩個集合的屬性內容
fs = gridfs.GridFS(db)

#查文件生產遊標
files = fs.find()

#獲取每一個檔案的物件
for file in files:
    print(file.filename)
    if file.filename == `file.jpg`:
        with open(file.filename,`wb`) as f:
            #從資料庫讀取出來
            data = file.read()
            #寫入本地
            f.write(data)

conn.close()


相關文章