2017-06-24

mLab 雲端資料庫與 Python 之 CRUD – I. 新增/查詢篇

開發應用程式時,對資料庫最常見也最主要的處理,就是進行資料的「新增」、「修改」、「刪除」、「查詢」等動作,簡稱為資料庫的CRUD。一起來了解要怎麼操作囉…


「新增」、「修改」、「刪除」、「查詢」這4個動作,在對關聯式資料庫極為重要的SQL語言中,被稱為「資料操縱語言 (Data Manipulation Language, DML)」,負責對資料庫物件執行資料存取工作。程式開發者習慣稱之為資料庫的CRUD - C(create 新增)、R(read 讀取/查詢)、U(update 更新/修改)、D(delete 刪除)。

MongoDB 是 NoSQL DB,並不需要像關聯式資料庫必須先學習 SQL語言 (至少需要了解 select, insert, update, delete) 才能操作,只要理解 MongoDB 處理CRUD的方法 (method / function) 就可以了,所以簡單得多囉!

我們接續《mLab - DBaaS 雲端 MongoDB 與 Python 快速試作範例》來玩玩 mLab 資料庫的CRUD吧!

C (create 新增)
我們同樣使用 Python 的 PyMongo 套件來對 mLab 進行操作, PyMongo 新增資料主要有 insert_one(), insert_many() 兩個方法,Python 的命名相當直覺,您一定很容易就猜出來 insert_one() 是新增一筆資料, insert_many() 是新增多筆資料。新增語法為:


InsertOneResult = insert(document)
l   document (必要):要新增的資料。
l   InsertOneResult:新增結果,將回傳新增的 _id

1、先 import pymongo,然後建立資料庫連線,取得資料表。

import pymongo
from pymongo import MongoClient
myClient = MongoClient("Your_MongoDB_URI")
myDB = myClient.mlabtest01
myCollection = myDB.coll01

2、我們可以直接把要新增的資料放在 insert_one() 裡, insert_one() 會接在某個資料表 (collection)後,因為資料是加在資料表裡的,並把執行後的結果存到 result 中。若執行成功會將新增資料的 id 存入 result,可以 result.inserted_id 來查看。
count() 一下,變成6筆資料了,mLab 中的資料也多了一筆。

result = myCollection.insert_one({"name":"Broccoli","price":"40","stock":"5"})
result.inserted_id
myCollection.count()



3、也可以把要新增的資料放在變數中,再放進 insert_one() 的參數。我們可以將應該存入數值的"庫存數 (stock)" 欄位存入 "缺貨中" 字串,這是 NoSQL 的資料型態彈性。

myNewDoc = {"name":"梨子","price":"50","stock":"缺貨中"}
result = myCollection.insert_one(myNewDoc)
result.inserted_id
myCollection.count()




4、另一個新增多筆資料 insert_many() 的用法就不難猜出來了吧!變數中以 JSON 格式設定多筆資料,然後放入 insert_many() 的參數,不過這時要顯示 id 就必須加 s 囉 result.inserted_ids。

此處,我們甚至在新增其中一筆資料時,動態地為資料表 (collection) 增加了一個"單位 (unit)"欄位,可看出 MongoDB 動態 Schema 的強大彈性。資料表 (collection) 可以隨時視需求增加欄位,以應付網路資料多變的特性。但事情總是兩面的,如果每一位開發者都隨意的新增欄位,沒有統一的管理,最後這張資料表會長怎麼樣?裡面的資料是什麼意義?誰會知道呢?

在 mLab 裡真的增加了一個 Unit 欄位了。

myNewDocs = [{"name":"Cherry","price":30,"stock":40},{"name":"Fig","unit":"bag","price":100,"stock":20}]
result = myCollection.insert_many(myNewDocs)
result.inserted_ids
myCollection.count()



以上即為CRUD中的C (create) 新增資料。

R (read 讀取/查詢)
PyMongo 讀取/查詢資料有 find_one(), find() 兩個方法,前一個範例中已經介紹過 find_one() 顯示資料表的第一筆資料, find() 顯示所有資料,快速複習一下,這裡要介紹的是加上條件 (condition) 的查詢。


ResultSet = find(filter,limit,sort)
l   filter (非必要):查詢條件。
l   limit (非必要):回傳result set的最大資料筆數。
l   sort (非必要):指定排序方式。
l   findDocument:回傳值,查詢結果result set


print(myCollection.find_one())    #顯示第一筆資料
for myDocs in myCollection.find():
    print(myDocs)   #顯示所有資料



1、找某個值 (等於)
若我們想找出 coll01 資料表中名字為 Cherry 的資料,在 find() 參數裡加入查詢的欄位和資料,再用 for loop 將裡面的資料列出來 (因為查詢結果可能是0筆,也可能是很多筆,我們事先不會知道)。

for myDocs in myCollection.find({"name": "Cherry"}):   # 查詢名字 name 是 Cherry 的資料
print(myDocs)



2、找大於某個值 - Greater Than Operator ($gt)
若我們想找出 coll01 資料表中價格大於100的資料,同樣在 find() 參數裡加入查詢的欄位和資料,再用 for loop 將資料列出來。要注意 $gt 比較的是數值,若資料存入時不是以數值輸入,就比較不出來囉 (你可以看到NoSQL資料型態彈性會發生的問題)。

for myDocs in myCollection.find({"price": {"$gt": 100}}):  # 查詢價格大於 100
print(myDocs)


3、找小於某個值 - Less Than Operator ($lt)
若我們想找出 coll01 資料表中庫存數小於30的資料,你會發現庫存數欄位若以字串輸入的資料都出不來 (如 Broccoli)。

for myDocs in myCollection.find({"stock": {"$lt": 30}}):  # 查詢庫存數小於 30
print(myDocs)


4、條件組合 (Combine Conditions)
4-1、且 (AND)
"且" 條件很簡單,find() 裡再加一組條件以逗號 (,) 分隔就是 AND,但必須在同一組大括號 ({ })裡。

for myDocs in myCollection.find({"price": {"$gt": 100},"stock": {"$lt": 30}}):  # 查詢價格大於 100 且 庫存數小於 30
print(myDocs)


4-2、或 (OR)
"或" 則要在條件前加上 ("$or":),不同組條件間也是用逗號 (,) 分隔。
查詢也可以寫成這種形式,把查詢的結果存到變數 myCursor 中,再用 for loop 將資料列出來。

myCursor = myCollection.find({"$or": [{"name": "apple"}, {"stock": "1A"}]})  # 查詢名字為 apple 或庫存數為 1A
for myDocs in myCursor:
print(myDocs)


5、排序
排序也是查詢時常用到的功能,PyMongo 以 sort() 進行排序,並以 pymongo.ASCENDING (ascending 昇冪/遞增/由小到大)、pymongo.DESCENDING (descending 降冪/遞減/由大到小) 參數控制排序方式。
同樣您會發現價格欄位不是用數值存入的,就不受控制了。

for myDocs in myCollection.find().sort([("price", pymongo.ASCENDING)]):  # 以價格遞增排序(由小到大)
print(myDocs)

for myDocs in myCollection.find().sort([("name", pymongo.ASCENDING),("price", pymongo.DESCENDING )]):  # 兩個排序條件
print(myDocs)


新增/查詢就先介紹到這囉,下次再繼續修改/刪除。