MongoDB與python交互

上一篇文章已經(jīng)運(yùn)用了Pymongo這個包,本篇文章詳細(xì)介紹下Pymongo的使用

1.Pymongo

PyMongo是Mongodb的Python接口開發(fā)包泪姨,是使用python和Mongodb的推薦方式。

官方文檔

2.安裝

進(jìn)入虛擬環(huán)境
sudo pip install pymongo
或源碼安裝
python setup.py

3.使用

  • 導(dǎo)入模塊
import pymongo 
#或者
from pymongo import MongoClient
  • 建立于MongoClient 的連接:
client = MongoClient('localhost', 27017) 
# 或者 
client = MongoClient('mongodb://localhost:27017/') 
  • 得到數(shù)據(jù)庫
db = client.test_database
# 或者 
db = client['test-database'] 
  • 得到一個數(shù)據(jù)集合
collection = db.test_collection
# 或者 
collection = db['test-collection'] 
  • MongoDB中的數(shù)據(jù)使用的是類似Json風(fēng)格的文檔
>>> import datetime 
>>> post = {"author": "Mike",    
            "text": "My first blog post!",    
            "tags": ["mongodb", "python", "pymongo"], 
            "date": datetime.datetime.utcnow()} 
  • 插入一個文檔
>>> posts = db.posts 
>>> post_id = posts.insert_one(post).inserted_id 
>>> post_id 
ObjectId('...') 
  • 查找一條數(shù)據(jù)
>>> posts.find_one() 
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}   
>>> posts.find_one({"author": "Mike"}) 
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}   
>>> posts.find_one({"author": "Eliot"}) 
>>> 
  • 通過ObjectId來查找
>>> post_id ObjectId(...) 
>>> posts.find_one({"_id": post_id})
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']} 
  • 不要轉(zhuǎn)化ObjectId的類型為String
>>> post_id_as_str = str(post_id) 
>>> posts.find_one({"_id": post_id_as_str}) # No result 
>>> 
  • 如果post_id是字符串
from bson.objectid import ObjectId  
# The web framework gets post_id from the URL and passes it as a string def get(post_id):   
    # Convert from string to ObjectId:   
    document = client.db.collection.find_one({'_id': ObjectId(post_id)}) 
  • 多條插入
>>> new_posts = [{"author": "Mike", 
                  "text": "Another post!", 
                  "tags": ["bulk", "insert"], 
                  "date": datetime.datetime(2009, 11, 12, 11, 14)}, 
                  {"author": "Eliot", 
                  "title": "MongoDB is fun", 
                  "text": "and pretty easy too!", 
                  "date": datetime.datetime(2009, 11, 10, 10, 45)}] 
>>> result = posts.insert_many(new_posts) 
>>> result.inserted_ids 
[ObjectId('...'), ObjectId('...')] 
  • 查找多條數(shù)據(jù)
>>> for post in posts.find(): 
...  post 
... 
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']} 
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']} 
{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'} 

#查找多個文檔2
cur=stu.find()
cur.next()
  • 獲取集合的數(shù)據(jù)條數(shù)
posts.count() 

#滿足某種查找條件的數(shù)據(jù)條數(shù):
posts.find({"author": "Mike"}).count() 
  • 范圍查找
#比如說時間范圍
>>> d = datetime.datetime(2009, 11, 12, 12) 
>>> for post in posts.find({"date": {"$lt": d}}).sort("author"): 
...  print post 
{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'} 
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']} 

4.mongoDB其它操作

1.超級管理員

  • 為了更安全的訪問mongodb蔑担,需要訪問者提供用戶名和密碼彭沼,于是需要在mongodb中創(chuàng)建用戶
    采用了角色-用戶-數(shù)據(jù)庫的安全管理方式
    常用系統(tǒng)角色如下:

root:只在admin數(shù)據(jù)庫中可用,超級賬號遭垛,超級權(quán)限
Read:允許用戶讀取指定數(shù)據(jù)庫
readWrite:允許用戶讀寫指定數(shù)據(jù)庫

  • 創(chuàng)建超級管理用戶
use admin
db.createUser({
    user:'admin',
    pwd:'123',
    roles:[{role:'root',db:'admin'}]
})
  • 添加訪問用戶
mongo進(jìn)入操作界面

use admin   # 指定數(shù)據(jù)庫

db.addUser(“用戶名”, “密碼”) 添加用戶    # 可以使用,已經(jīng)提示過時

db.createUser(“用戶名”, “密碼”) 添加用戶

  • 啟用安全認(rèn)證
    修改配置文件
sudo vi /etc/mongod.conf
  • 啟用身份驗(yàn)證
    注意:keys and values之間一定要加空格, 否則解析會報錯
security:
  authorization: enabled
  • 重啟服務(wù)
sudo service mongod stop
sudo service mongod start
  • 終端連接
 mongo -u 'admin' -p '123' --authenticationDatabase 'admin'
  • 普通用戶管理
    使用超級管理員登錄操灿,然后進(jìn)入用戶管理操作
    查看當(dāng)前數(shù)據(jù)庫的用戶
use test1
show users
  • 創(chuàng)建普通用戶
db.createUser({
    user:'t1',
    pwd:'123',
    roles:[{role:'readWrite',db:'test1'}]
})
  • 終端連接
mongo -u t1 -p 123 --authenticationDatabase test1
  • 切換數(shù)據(jù)庫锯仪,執(zhí)行命令查看效果
    修改用戶:可以修改pwd、roles屬性
db.updateUser('t1',{pwd:'456'})

2.主從雙備

復(fù)制的優(yōu)點(diǎn)

  • 復(fù)制提供了數(shù)據(jù)的冗余備份趾盐,并在多個服務(wù)器上存儲數(shù)據(jù)副本庶喜,提高了數(shù)據(jù)的可用性,并可以保證數(shù)據(jù)的安全性
  • 復(fù)制還允許從硬件故障和服務(wù)中斷中恢復(fù)數(shù)據(jù)
  • 數(shù)據(jù)備份
  • 數(shù)據(jù)災(zāi)難恢復(fù)
  • 讀寫分離
  • 高(24* 7)數(shù)據(jù)可用性
  • 無宕機(jī)維護(hù)
  • 副本集對應(yīng)用程序是透明
  • 復(fù)制的工作原理
  • 復(fù)制至少需要兩個節(jié)點(diǎn)A救鲤、B...
  • A是主節(jié)點(diǎn)久窟,負(fù)責(zé)處理客戶端請求
  • 其余的都是從節(jié)點(diǎn),負(fù)責(zé)復(fù)制主節(jié)點(diǎn)上的數(shù)據(jù)
  • 節(jié)點(diǎn)常見的搭配方式為:一主一從本缠、一主多從
  • 主節(jié)點(diǎn)記錄在其上的所有操作斥扛,從節(jié)點(diǎn)定期輪詢主節(jié)點(diǎn)獲取這些操作,然后對自己的數(shù)據(jù)副本執(zhí)行這些操作丹锹,從而保證從節(jié)點(diǎn)的數(shù)據(jù)與主節(jié)點(diǎn)一致
  • 主節(jié)點(diǎn)與從節(jié)點(diǎn)進(jìn)行數(shù)據(jù)交互保障數(shù)據(jù)的一致性
  • 復(fù)制的特點(diǎn)
  • N 個節(jié)點(diǎn)的集群
  • 任何節(jié)點(diǎn)可作為主節(jié)點(diǎn)
  • 所有寫入操作都在主節(jié)點(diǎn)上
  • 自動故障轉(zhuǎn)移
  • 自動恢復(fù)

案例:

  • step1:創(chuàng)建數(shù)據(jù)庫目錄t1稀颁、t2
    在Desktop目錄下演示,其它目錄也可以楣黍,注意權(quán)限即可
mkdir t1
mkdir t2
  • step2:使用如下格式啟動mongod匾灶,注意replSet的名稱是一致的
mongod --bind_ip 192.168.10.110 --port 27018 --dbpath ~/Desktop/t1 -->replSet rs0
mongod --bind_ip 192.168.10.111 --port 27019 --dbpath ~/Desktop/t2 -->replSet rs0
  • step3:連接主服務(wù)器,此處設(shè)置192.168.10.110:27018為主服務(wù)器
mongo --host 192.168.10.110 --port 27018
  • step4:初始化
rs.initiate()
  • step5:查看當(dāng)前狀態(tài)
rs.status()
  • step6:添加復(fù)本集
rs.add('192.168.10.111:27019')
  • step8:新開窗口租漂,連接第二個mongo服務(wù)
mongo --host 192.168.10.111 --port 27019
  • step9:向主服務(wù)器中插入數(shù)據(jù)
use test1
for(i=0;i<10;i++){db.t1.insert({_id:i})}
db.t1.find()
  • step10:在從服務(wù)器中插查詢
    說明:如果在從服務(wù)器上進(jìn)行讀操作阶女,需要設(shè)置rs.slaveOk()
rs.slaveOk()
db.t1.find()
  • 其它說明
    刪除從節(jié)點(diǎn)
rs.remove('192.168.10.111:27019')

關(guān)閉主服務(wù)器后颊糜,再重新啟動,會發(fā)現(xiàn)原來的從服務(wù)器變?yōu)榱酥鞣?wù)器张肾,新啟動的服務(wù)器(原來的從服務(wù)器)變?yōu)榱藦姆?wù)器

3.備份

  • 語法
mongodump -h dbhost -d dbname -o dbdirectory

#例
sudo mkdir test1bak
sudo mongodump -h 192.168.10.110:27017 -d test1 -o ~/flex/test1bak
  • -h:服務(wù)器地址芭析,也可以指定端口號
  • -d:需要備份的數(shù)據(jù)庫名稱
  • -o:備份的數(shù)據(jù)存放位置,此目錄中存放著備份出來的數(shù)據(jù)

4.恢復(fù)

  • 語法
mongorestore -h dbhost -d dbname --dir dbdirectory

#例
mongorestore -h 192.168.10.110:27017 -d test2 --dir ~/flex/test1bak/test1
  • -h:服務(wù)器地址
  • -d:需要恢復(fù)的數(shù)據(jù)庫實(shí)例
  • -dir:備份數(shù)據(jù)所在位置

5.Mongodb與python交互

  • 之前學(xué)習(xí)了爬蟲吞瞪,現(xiàn)在我們把爬取得到的數(shù)據(jù)存儲于Mongodb中
#爬取英雄聯(lián)盟英雄信息詳情,并存儲

#-*- coding:utf-8 -*-
import pymongo
import requests
from bs4 import BeautifulSoup

#建立于MongoClient 的連接
client = pymongo.MongoClient('localhost',27017)
#得到數(shù)據(jù)庫
hero = client['hero']
#得到一個數(shù)據(jù)集合
sheet_tab = hero['sheet_tab']
url = 'http://lol.duowan.com/hero/'
req = requests.get(url)
soup = BeautifulSoup(req.text,'html.parser')
links = soup.find(id="champion_list").find_all('a')
for link in links:
    link = link['href']
    requ = requests.get(link)
    sop = BeautifulSoup(requ.text,'html.parser')
    data = {
    'title' : sop.find('h2',class_="hero-title").get_text(),
    'name' : sop.find('h1',class_="hero-name").get_text(),
    'tags' : sop.find('div',class_="hero-box ext-attr").find_all('span')[1].get_text(),
    'story' : sop.find('div',class_="hero-popup").find_all('p')[0].get_text(),
    }
    sheet_tab.insert_one(data)
  • 開啟mongo,運(yùn)行代碼
通過Robo 3T可視化工具我們可以看到抓取到了137條數(shù)據(jù)驾孔,并且已存儲到mongodb中

6.完成命令行項(xiàng)目:學(xué)生信息管理(基于Python2.7)

  • 代碼操作
#-*- coding:utf-8 -*-
import pymongo

def system():
    print('◆您將進(jìn)入數(shù)據(jù)庫管理系統(tǒng)芍秆,數(shù)據(jù)無價、謹(jǐn)慎操作翠勉!◆')
    print('◇1:查看數(shù)據(jù)◇')
    print('◇2:增加數(shù)據(jù)◇')
    print('◇3:修改數(shù)據(jù)◇')
    print('◇4:刪除數(shù)據(jù)◇')
    print('◇5:搜索數(shù)據(jù)◇')
    print('●6:退出數(shù)據(jù)庫管理系統(tǒng)●')

    # 建立與mongodb的連接
    client = pymongo.MongoClient('localhost', 27017)
    # 得到數(shù)據(jù)庫
    stu = client['stu']
    # 得到一個數(shù)據(jù)集合
    message = stu['message']

    while True:
        order = int(raw_input('請輸入相關(guān)指令:'))
        if order==1:
            exit = message.count()
            if exit==0:
                print('抱歉妖啥,數(shù)據(jù)庫中目前沒有相關(guān)數(shù)據(jù)!')
            else:
                for data in message.find():
                    content = data['name']+data['age']+data['sex']
                    print(content)
        elif order ==2:
            name = raw_input('請輸入學(xué)生姓名:')
            age = raw_input('請輸入學(xué)生年齡:')
            sex = raw_input('請輸入學(xué)生性別(男/女):')
            data = {
                'name':name,
                'age':age,
                'sex':sex,
            }
            message.insert_one(data)
            print ('添加成功对碌!')

        elif order == 3:
            name = raw_input('請輸入要修改的學(xué)生姓名:')
            exit = message.count({'name': name})
            if exit != 0:
                age = raw_input('請輸入修改后的學(xué)生年齡:')
                message.update({'name':name},{'$set':{'age':age}})
                print('修改成功')
            else:
                print '抱歉荆虱,數(shù)據(jù)庫中沒有這個學(xué)生的信息!'

        elif order == 4:
            name = raw_input('請輸入要刪除的學(xué)生姓名:')
            exit = message.count({'name': name})
            if exit != 0:
                message.remove({'name':name})
                print('刪除成功')
            else:
                print '抱歉朽们,數(shù)據(jù)庫中沒有這個學(xué)生的信息怀读!'

        elif order == 5:
            name = raw_input('請輸入要查詢的學(xué)生姓名:')
            exit = message.count({'name':name})
            if exit!=0:
                data = message.find_one({'name':name})
                content = data['name']+data['age']+data['sex']
                print content
            else:
                print '抱歉,數(shù)據(jù)庫中沒有這個學(xué)生的信息骑脱!'

        elif order == 6:
            print('感謝您的使用菜枷!')
            break
        else:
            print('您的輸入有誤,請輸入有效指令(1/2/3/4/5)')

if __name__ == '__main__':
    system()
測試結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叁丧,一起剝皮案震驚了整個濱河市啤誊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拥娄,老刑警劉巖蚊锹,帶你破解...
    沈念sama閱讀 210,835評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異稚瘾,居然都是意外死亡牡昆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評論 2 383
  • 文/潘曉璐 我一進(jìn)店門孟抗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迁杨,“玉大人,你說我怎么就攤上這事凄硼∏π” “怎么了?”我有些...
    開封第一講書人閱讀 156,481評論 0 345
  • 文/不壞的土叔 我叫張陵摊沉,是天一觀的道長狐史。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么骏全? 我笑而不...
    開封第一講書人閱讀 56,303評論 1 282
  • 正文 為了忘掉前任苍柏,我火速辦了婚禮,結(jié)果婚禮上姜贡,老公的妹妹穿的比我還像新娘试吁。我一直安慰自己,他們只是感情好楼咳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,375評論 5 384
  • 文/花漫 我一把揭開白布熄捍。 她就那樣靜靜地躺著,像睡著了一般母怜。 火紅的嫁衣襯著肌膚如雪余耽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,729評論 1 289
  • 那天苹熏,我揣著相機(jī)與錄音碟贾,去河邊找鬼。 笑死轨域,一個胖子當(dāng)著我的面吹牛袱耽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疙挺,決...
    沈念sama閱讀 38,877評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼扛邑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铐然?” 一聲冷哼從身側(cè)響起蔬崩,我...
    開封第一講書人閱讀 37,633評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎搀暑,沒想到半個月后沥阳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,088評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡自点,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,443評論 2 326
  • 正文 我和宋清朗相戀三年桐罕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桂敛。...
    茶點(diǎn)故事閱讀 38,563評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡功炮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出术唬,到底是詐尸還是另有隱情薪伏,我是刑警寧澤,帶...
    沈念sama閱讀 34,251評論 4 328
  • 正文 年R本政府宣布粗仓,位于F島的核電站嫁怀,受9級特大地震影響设捐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塘淑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,827評論 3 312
  • 文/蒙蒙 一萝招、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧存捺,春花似錦槐沼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至具滴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間师倔,已是汗流浹背构韵。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留趋艘,地道東北人疲恢。 一個月前我還...
    沈念sama閱讀 46,240評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像瓷胧,于是被迫代替她去往敵國和親显拳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,435評論 2 348

推薦閱讀更多精彩內(nèi)容