上一篇文章已經(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)行代碼
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()