以前搞過python和mongodb,時間長了 就忘了, 並且每次找百度也不是特別方便, 今天就此整理一下。首先來看最基礎的
CRUD操作
from pymongo import MongoClient #創建連接 conn = MongoClient("mongodb://root:root@127.0.0.1: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("mongodb://root:root@127.0.0.1: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("mongodb://root:root@127.0.0.1:27017/") db = conn.images myset = db.img #存儲 f = open('/root/test.jpg','rb') #轉換為mongodb的二進制數據存儲形式 content = bson.binary.Binary(f.read()) #插入到數據庫 myset.insert({'filename':'test.jpg','data':content}) #提取 data = myset.find_one({'filename':'test.jpg'}) #通過字典獲取到數據庫內容寫入本地 with open('/root/test2.jpg','wb') as f: f.write(data['data']) conn.close()
借用GridFS來處理文件
from pymongo import MongoClient from gridfs import * conn = MongoClient("mongodb://root:root@127.0.0.1:27017/") db = conn.image #存儲 f = open('/root/test.jpg','rb') #創建寫入流 imgput = GridFS(db) #將數據寫入,文件類型和名稱通過前面的分割得到 insertimg=imgput.put(f,content_type='jpg',filename='/root/test.jpg') f.close() #創建成功后,會在集合中生成fs.flies和fs.chunks gridFS = GridFS(db, collection="fs") for grid_out in gridFS.find(): data = grid_out.read() # 獲取圖片數據 outf = open('/root/test3.jpg','wb')#創建文件 outf.write(data) # 存儲圖片 outf.close() conn.close()
有關GridFS的描述:
一、概述
GridFS是基於mongodb存儲引擎是實現的“分布式文件系統”,底層基於mongodb存儲機制,和其他本地文件系統相比,它具備大數據存儲的多個優點。GridFS適合存儲超過16MB的大型文件,不過16M數據在當今互聯網時代,已經不足為奇。我們可以使用GridFS構建大規模的“圖片服務器”、“文檔服務器”、“視頻、音頻”文件服務器,GridFS對於web應用,可以結合nginx插件“ningx-gridfs”能夠簡單的實現負載均衡等特性,非常便捷;可以簡單認為GridFS是為web應用而生。個人認為,目前架構比較簡單的NoSQL文件系統中GridFS是最優秀的。
GridFS並不是將單個文件直接存儲為一個document,而是將文件分成多個parts或者說chunks,然后將每個chunk作為作為一個單獨的document存儲,然后將chunks有序保存。默認情況下,GridFS的chunk大小位255k。GridFS使用2個collections來存儲這些文件,一個collection存儲文件的chunks(實際文件數據),另一個則存儲文件的metadata(用戶自定義的屬性,filename,content-type等)。
當用戶查詢GridFS中的文件時,客戶端或者driver將會重新按序組裝這些chunks。用戶可以range查詢文件,也可以獲取文件的任意部分的信息,比如:跳過(skip)視頻或者音頻(任何文件)的中間部,實現“range access of single file”。
對於mongodb而言,每個document最大尺寸為16M,如果想存儲一條數據(比如一個文件)超過16M,那么只能使用GridFS支持;GridFS可以支持單個文件尺寸達到數G,讀取文件時可以分段讀取。此外,GridFS可以從Mongodb的高性能、高可用特性中獲益,比如我們可以在“replica set”或者“sharding”架構模式下使用GridFS。
二、使用場景
document的大小超過16M是使用GridFS的條件之一,因為mongodb普通的collection無法支持16M以上的document,我們不得不選擇其他方案;在一些情況下,將這些大文件存儲在GridFS中,比直接存儲在本地文件系統中更加適合:
1)如果你的文件系統對每個目錄下文件的個數有限制(或者太多,將會影響文件的打開速度等)。
2)如果你的文件數據,有分數據中心鏡像保存(大數據情況,可用性保證)。
3)如果你希望訪問一個超大的文件,而不希望將它全部加入內存,而是有“range access”的情況,即分段讀取,那么GridFS天生就具備這種能力,你可以隨意訪問任意片段。
對於一個大文件,如果你希望原子性的更新它的全部內容,那么GridFS將不適合;比如同時更新一個文件的多個chunk,因為mongodb本身沒有事務機制。
對於小於16M的文件,比如一些圖片、CSS、js文件等,應該將它們直接存儲在普通的collection中而非GridFS(bindata,參見org.bson.types.Binary),因為它們通常較小,GridFS無法發揮其優勢。當然,你為了統一application的“文件系統”存儲方式,也可以將這些小文件保存在GridFS中,性能也不會差的太多,為了提升性能,對這些小文件,可以在存儲時手動設置它的chunkSize,避免文件被切分成多個chunks來提高性能。