孤荷凌寒自學python第五十九天嘗試使用python來讀訪問遠端MongoDb資料服務
孤荷凌寒自學python第五十九天嘗試使用python來讀訪問遠端MongoDb資料服務
(完整學習過程螢幕記錄視訊地址在文末)
今天是學習mongoDB資料庫的第五天。今天的感覺是,mongoDB資料庫我似乎根本就很難掌控呵!
一、首先系統學習了讀寫mongoDB資料庫的方法
以下筆記來自官方文件整理:
(官方文件:https://api.mongodb.com/python/current/index.html )
(一)指定資料庫
MongoDB中還分為一個個資料庫,我們接下來的一步就是指定要操作哪個資料庫,在這裡我以test資料庫為例進行說明,所以下一步我們需要在程式中指定要使用的資料庫。
db = client.test
呼叫client的test屬性即可返回test資料庫,當然也可以這樣來指定:
db = client['test']
兩種方式是等價的。
(二)指定集合
MongoDB的每個資料庫又包含了許多集合Collection,也就類似與關係型資料庫中的表,下一步我們需要指定要操作的集合,在這裡我們指定一個集合名稱為students,學生集合。還是和指定資料庫類似,指定集合也有兩種方式。
collection = db.students
#collection = db['students']
(三)插入資料
接下來我們便可以進行資料插入了,對於students這個Collection,我們新建一條學生資料,以字典的形式表示:
student = {
'id': '20170101',
'name': 'Jordan',
'age': 20,
'gender': 'male'
}
在這裡我們指定了學生的學號、姓名、年齡和性別,然後接下來直接呼叫collection的insert()方法即可插入資料。
result = collection.insert(student)
print(result)
在MongoDB中,每條資料其實都有一個_id屬性來唯一標識,如果沒有顯式指明_id,MongoDB會自動產生一個ObjectId型別的_id屬性。insert()方法會在執行後返回的_id值。
執行結果:
5932a68615c2606814c91f3d
當然我們也可以同時插入多條資料,只需要以列表形式傳遞即可,示例如下:
student1 = {
'id': '20170101',
'name': 'Jordan',
'age': 20,
'gender': 'male'
}
student2 = {
'id': '20170202',
'name': 'Mike',
'age': 21,
'gender': 'male'
}
result = collection.insert([student1, student2])
print(result)
返回的結果是對應的_id的集合,執行結果:
[ObjectId('5932a80115c2606a59e8a048'), ObjectId('5932a80115c2606a59e8a049')]
實際上在PyMongo 3.X版本中,insert()方法官方已經不推薦使用了,當然繼續使用也沒有什麼問題,官方推薦使用insert_one()和insert_many()方法將插入單條和多條記錄分開。
student = {
'id': '20170101',
'name': 'Jordan',
'age': 20,
'gender': 'male'
}
result = collection.insert_one(student)
print(result)
print(result.inserted_id)
執行結果:
<pymongo.results.InsertOneResult object at 0x10d68b558>
5932ab0f15c2606f0c1cf6c5
返回結果和insert()方法不同,這次返回的是InsertOneResult物件,我們可以呼叫其inserted_id屬性獲取_id。
對於insert_many()方法,我們可以將資料以列表形式傳遞即可,示例如下:
student1 = {
'id': '20170101',
'name': 'Jordan',
'age': 20,
'gender': 'male'
}
student2 = {
'id': '20170202',
'name': 'Mike',
'age': 21,
'gender': 'male'
}
result = collection.insert_many([student1, student2])
print(result)
print(result.inserted_ids)
insert_many()方法返回的型別是InsertManyResult,呼叫inserted_ids屬性可以獲取插入資料的_id列表,執行結果:
<pymongo.results.InsertManyResult object at 0x101dea558>
[ObjectId('5932abf415c2607083d3b2ac'), ObjectId('5932abf415c2607083d3b2ad')]
(四)查詢記錄
插入資料後我們可以利用find_one()或find()方法進行查詢,find_one()查詢得到是單個結果,find()則返回多個結果。
result = collection.find_one({'name': 'Mike'})
print(type(result))
print(result)
在這裡我們查詢name為Mike的資料,它的返回結果是字典型別,執行結果:
<class 'dict'>
{'_id': ObjectId('5932a80115c2606a59e8a049'), 'id': '20170202', 'name': 'Mike', 'age': 21, 'gender': 'male'}
可以發現它多了一個_id屬性,這就是MongoDB在插入的過程中自動新增的。
我們也可以直接根據ObjectId來查詢,這裡需要使用bson庫裡面的ObjectId。
from bson.objectid import ObjectId
result = collection.find_one({'_id': ObjectId('593278c115c2602667ec6bae')})
print(result)
其查詢結果依然是字典型別,執行結果:
{'_id': ObjectId('593278c115c2602667ec6bae'), 'id': '20170101', 'name': 'Jordan', 'age': 20, 'gender': 'male'}
當然如果查詢結果不存在則會返回None。
對於多條資料的查詢,我們可以使用find()方法,例如在這裡查詢年齡為20的資料,示例如下:
results = collection.find({'age': 20})
print(results)
for result in results:
print(result)
執行結果:
<pymongo.cursor.Cursor object at 0x1032d5128>
{'_id': ObjectId('593278c115c2602667ec6bae'), 'id': '20170101', 'name': 'Jordan', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('593278c815c2602678bb2b8d'), 'id': '20170102', 'name': 'Kevin', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('593278d815c260269d7645a8'), 'id': '20170103', 'name': 'Harden', 'age': 20, 'gender': 'male'}
返回結果是Cursor型別,相當於一個生成器,我們需要遍歷取到所有的結果,每一個結果都是字典型別。
如果要查詢年齡大於20的資料,則寫法如下:
results = collection.find({'age': {'$gt': 20}})
在這裡查詢的條件鍵值已經不是單純的數字了,而是一個字典,其鍵名為比較符號$gt,意思是大於,鍵值為20,這樣便可以查詢出所有年齡大於20的資料。
比較符號的含義歸納:
$lt 小於 示例:{'age': {'$lt': 20}}
$gt 大於 示例:{'age': {'$gt': 20}}
$lte 小於等於 示例:{'age': {'$lte': 20}}
$gte 大於等於 示例: {'age': {'$gte': 20}}
$ne 不等於 示例: {'age': {'$ne': 20}}
$in 在範圍內 示例: {'age': {'$in': [20, 23]}}
$nin 不在範圍內 示例:{'age': {'$nin': [20, 23]}}
二、根據上面的系統學習,感覺很輕鬆搞定,於是開始測試
```
from pymongo import MongoClient
import _mty
import _mf
import _mre
import _cl
def msgbox(info,titletext='孤荷凌寒的對話方塊QQ578652607',style=0,isShowErrMsg=False):
return _mty.msgboxGhlh(info,titletext,style,isShowErrMsg)
def secondConnect():
#--指明資料庫伺服器的地址與埠號:
stru=_mf.readAllTextFromTxtFileGhlh('u.txt')
strp=_mf.readAllTextFromTxtFileGhlh('p.txt')
strhost='mongodb://' + stru + ':' + strp + '@cluster0-zr7xj.mongodb.net/?authMechanism=SCRAM-SHA-256'
#--建立連線
client=MongoClient(strhost,tz_aware=True,connect=True)
#client=MongoClient("cluster0-zr7xj.mongodb.net",username=stru,password=strp,authMechanism='SCRAM-SHA-256',connect=False)
#-- 獲取資料庫的命名標識
#print(client.admin.command('ismaster'))
db2=client.ghlhfirst
#--獲取其中的一個集合物件
jh=db2.ghlhone
#msgbox(str(jh.info))
#--查詢這個集合其中的記錄
print(jh.find_one({"姓名":"張三"}))
secondConnect()
```
每次前面都執行正常,總是到了:
print(jh.find_one({"姓名":"張三"}))
這句時要等大概一分鐘,然後報錯:
pymongo.errors.ServerSelectionTimeoutError: cluster0-zr7xj.mongodb.net:27017: [Errno 11001] getaddrinfo failed
於是我就開始不停的搜尋,前後花了至少3個多小時,反覆測試,到底為什麼連線上了卻不能讀出(查詢)出任何內容來呢,真的弄得自己筋疲力盡。
後來想到是不是一開始就沒有連線上呢?
經過認真思考,發現還真的是一開始就沒有連線上MongoDB的遠端伺服器,這才明白昨天並沒有根本上解決問題!!
真是個莫大的烏龍!
原來前面的語句只是將連線資訊等儲存起來罷了(詳細見Mongo_Client.py檔案(就是Pip安裝的那個pymongodb模組中的檔案))
直到:
jh.find_one({"姓名":"張三"})
這一語句時才真正去連線伺服器,這就是為什麼這個語句要執行等待一分鐘左右才最終報錯的原因。真是個大坑。
這意味著,mongoDB遠端伺服器其實根本就沒有被連線上,始終沒有解決問題。
決定明天只好開始佈置本地MongoDB資料庫服務了。
因為學習時間有限,今天的學習只能擱到這兒,還懇請高手能夠指點迷津,萬分感激。
——————————
今天整理的學習筆記完成,最後例行說明下我的自學思路:
根據過去多年我自學各種程式語言的經歷,認為只有真正體驗式,解決實際問題式的學習才會有真正的效果,即讓學習實際發生。在2004年的時候我開始在一個鄉村小學自學電腦 並學習vb6程式語言,沒有學習同伴,也沒有高師在上,甚至電腦都是孤島(鄉村那時還沒有網路),有的只是一本舊書,在痛苦的自學摸索中,我找到適應自己零基礎的學習方法:首先是每讀書的一小節就作相應的手寫筆記,第二步就是上機測試每一個筆記內容是否實現,其中會發現書中講的其實有出入或錯誤,第三步就是在上機測試之後,將筆記改為電子版,形成最終的修訂好的正確無誤的學習筆記 。
通過反覆嘗試錯誤,在那個沒有分享與交流的黑暗時期我摸黑學會了VB6,爾後接觸了其它語言,也曾聽過付費視訊課程,結果發現也許自己學歷果然太低,就算是零基礎的入門課程,其實也難以跟上進度,講師的教學多數出現對初學者的實際情況並不瞭解的情況,況且學習者的個體也存在差異呢?當然更可怕的是收費課程的價格往往是自己難以承受的。
於是我的所有程式設計學習都改為了自學,繼續自己的三步學習筆記法的學習之路。
當然自學的最大問題是會走那麼多的彎路,沒有導師直接輸入式的教學來得直接,好在網路給我們帶來無限搜尋的機會,大家在網路上的學習日誌帶給我們共享交流的機會,而QQ群等交流平臺、網路社群的成立,我們可以一起自學,互相批評交流,也可以獲得更有效,更自主的自學成果。
於是我以人生已過半的年齡,決定繼續我的程式設計自學之路,開始學習python,只希望與大家共同交流,一個人的獨行是可怕的,只有一群人的共同前進才是有希望的。
誠摯期待您的交流分享批評指點!歡迎聯絡我加入從零開始的自學聯盟。
這個時代網際網路成為了一種基礎設施的存在,於是本來在孤獨學習之路上的我們變得不再孤獨,因為網路就是一個新的客廳,我們時刻都可以進行沙龍活動。
非常樂意能與大家一起交流自己自學心得和發現,更希望大家能夠對我學習過程中的錯誤給予指點——是的,這樣我就能有許多免費的高師了——這也是分享時代,社群時代帶來的好福利,我相信大家會的,是吧!
根據完全共享的精神,開源互助的理念,我的個人自學錄製過程是全部按4K高清視訊錄製的,從手寫筆記到驗證手寫筆記的上機操作過程全程錄製,但因為4K高清檔案太大均超過5G以上,所以無法上傳至網路,如有需要可聯絡我QQ578652607對傳,樂意分享。上傳分享到百度網盤的只是壓縮後的720P的視訊。
我的學習過程錄影百度盤地址分享如下:(清晰度:1280x720)
連結:https://pan.baidu.com/s/1pxsntZ5bMRs1vr9uHSW7Fg
提取碼:u6mu
喜馬拉雅語音筆記:
https://www.ximalaya.com/keji/19103006/150385573
bilibili: