[MongoDB] 學習筆記(一) - 安裝、基礎CRUD、外部輸入資料、Data Type
Tags: Mongodb

而 filter 可以使用條件式的方式書寫，如我要查詢field為a中，大於0的數值，則 filter 為 {"a": {$gt:0}} ，其他operators可以參考下面網址。

// 插入程式碼 //

db.employee.drop()

db.employee.insertOne({

"first_name": "Robin",

"last_name": "Jackman",

})

db.employee.insertOne([{

"first_name": "Robin",

"last_name": "Jackman",

},

{'a':1, 'b':2

}])

db.employee.insertMany([{

"first_name": "Robin",

"last_name": "Jackman",

},

{'a':1, 'b':2

}])

db.employee.find().pretty() // 刪除程式碼 //

db.employee.drop()

db.employee.insertMany(

[

{

"a":1,

"b":2

},

{

"a":1,

"b":2

},

{

"a":1,

"b":2

}

])

db.employee.find()

db.employee.deleteOne({"a":1})

db.employee.find()

db.employee.deleteMany({"a":1})

db.employee.find() db.employee.deleteMany({"a":{"$gt":0}})

Document的查詢、更新

與前面相似，查詢、更新分別也有針對一個與多個document操作的函數。一次查詢一個document的函數 db.<collection_name>.findOne(filter, projection) ，如果設定的條件找到多的結果，則回傳第一個；而一次查詢多個的函數為 db.<collection_name>.find(filter, projection) 。如果filter為空，則回傳所有結果；projection則為選擇需要的field，如果field為空，則回傳所有篩選結果。

而 projection 的寫法為{ <field1>: <value>, <field2>: <value> … }，如果需要篩選field1，則會寫成 {field: 1} 。

針對單一ducoment進行更新的函數為 db.<collection_name>.updateOne(filter, oupdate_object) ，而針對多個ducoment進行更新的函數，則為 db.<collection_name>.updateMany(filter, oupdate_object) ，而 oupdate_object 為 $set(指定field: 更新數值) 。

所以當我想要將資料庫中，薪水大於1000的員工，都變成500，那就會寫成 db.<collection_name>.updateMany("Salary":{"$gt":1000}, $set("Salary":500)) ，相關的執行結果如圖8.。

圖8. 查詢、更新執行結果

// 建立document//

db.employee.drop()

db.employee.insertMany(

[

{

"Salary":1000,

"_id":0

},

{

"Salary":1000,

"_id":1

},

{

"Salary":1000,

"_id":2

},

{

"Salary":2000,

"_id":3

}

]) // 查詢程式碼 //

db.employee.findOne()

db.employee.findOne({'Salary':1000})

db.employee.find()

db.employee.find({'Salary':1000}) // 更新程式碼 //

db.employee.updateOne({"Salary":{"$gte":1000}}, {$set:{"Salary":500}})

db.employee.find() db.employee.updateMany({"Salary":{$gte:1000}}, {$set:{"Salary":900}})

db.employee.find() db.employee.updateOne({"_id":0}, {$set:{"Position":"PM"}})

db.employee.find() db.employee.updateMany({"_id":{$gte:2}}, {$set:{"Position":"RD"}})

db.employee.find() db.employee.find({"Salary":{$gte:900}}, {"Position":1})

Document的覆蓋

當你想要將一個document以另一個document進行覆蓋時，有兩個函數可以做到這件事，document進行覆蓋的 db.<collection_name>.replaceOne(filter, document) 與針對所有結果進行覆蓋的 db.<collection_name>.update(filter, document/oupdate_object) 。

其中 db.<collection_name>.update 的第二個參數，如果你給的是 document ，則效果與 db.<collection_name>.replaceOne 相同；而如果是給 oupdate_object 則效果與 db.<collection_name>.updateOne 相同。

但需要注意的一點是，這裡覆蓋的document，他是將document中的field, value進行替換，但是document的_id是不會變的，而如果你嘗試要更改_id，則會回報錯誤。執行結果如圖9.。

圖9. 替換執行結果

// 替換程式碼 //

db.employee.drop()

db.employee.insertMany(

[

{

"Salary":1000,

"_id":0

},

{

"Salary":1000,

"_id":1

},

{

"Salary":1000,

"_id":2

},

{

"Salary":2000,

"_id":3

}

])

db.employee.replaceOne({"_id":0}, {"Position":"PM"})

db.employee.find()

db.employee.update({"_id":1}, {$set:{"Position":"HR"}})

db.employee.find()

db.employee.update({"_id":2}, {"Position":"RD"})

db.employee.find()

db.employee.update({"_id":3}, {"Position":"RD", '_id':4})

db.employee.find()

db.employee.replaceOne({"_id":3}, {"Position":"SA", '_id':3})

db.employee.find()

外部輸入資料 - mongoimport

當我們想要直接從外部import json檔案進MongoDB時，可以使用 mongoimport 。這個指令是要在cmd的環境下執行的，不是在mongo的環境。但如果是windows的使用者，有可能會發生無法找到執行檔的問題，此時就要下載相關的toolbox，連結如下：

下載下來解壓縮後，會出現一個bin的資料夾，裡面就可以看到mongoimport的執行檔，如下圖。此時將這些執行檔複製到mongo的bin資料夾(就是上面加入環境變數的路徑)，此時再cmd中就能執行 mongoimport 的指令。

使用方法是這樣的，其中 -d 指的是資料庫的名字， -c 是collection的名字， -jsonArray 是指輸入的檔案格式， -drop 則是指刪除先前創建的collection，重新建立一個新的collection。

mongoimport <json路徑> -d <db_name> -c <collection_name> -jsonArray --drop

詳細的使用方法見 -help ，執行結果如下圖。可以看到他連結到local mongdb的路徑，並且drop掉test.test這個collection，最後成功導入2個documents。

常用的Data Type

MongoDB的shell，其實就是javascript的Client，所以裡面是可以寫javascript語法的。所以一些MongoDB的資料格式，會透過javascript創建，再儲存進MongoDB中。如果是以其他語言使用，也會有對應的driver可以處理，支援的drive可以參考下面網站。

https://docs.mongodb.com/drivers/

String、Number、Boolean

如果我們想要看一個value的data type，可以透過先以 var 將物件存下來，再以 typeof 查看。而存取的方式，則可以用 db.<collection_name>.findOne 儲存，再呼叫裡面的field。舉例而言 var result = db.employee.findOne({Salary:1000}) 就是將篩選的結果存在 result 裡面，此時我要看Salary的內容時，就可以使用 result.Salary 。執行結果如圖10，像是 500 是 number 、 true 是 boolean 、 HR 是 string ，而其他像是array會是object，都會被歸在 object 中。

圖10. 資料類型查看

db.employee.drop()

db.employee.insertMany([

{

"Salary":500,

"_id":0

},

{

"Position":"HR",

"Salary":1000,

"Tenure":4.56,

"Stay":true,

"Phone_number":{

home:22222222,

mobile:0911111111

}

}]

) var result = db.employee.findOne({Salary:1000})

result.Position

typeof result.Position

result.Salary

typeof result.Salary

result.Stay

typeof result.Stay

result._idt

typeof result._idt

result.Phone_number

typeof result.Phone_number

時間數據類型 date

時間類型是挺煩的，很容易因為起算的時區不同而有誤差。常用的function是 Date ，而他基本上有三種用法：

不輸入參數 new Date() ：顯示現在時間 輸入數字 new Date(number) ：顯示自1970-01-01以來過了幾毫秒，如果輸入 new Date(1000*60) 則結果會是 ISODate("1970-01-01T00:01:00Z") 過了一分鐘。 輸入日期格式文字 new Date(string) ：舉例而言，你可以輸入 new Date("2018-5-1") ，結果會是 ISODate("2018-05-01T00:00:00Z") 。而可以接受的日期格式可以參考，如果輸入錯誤的格式會出現NA

圖11. 時間類型變數執行結果

new Date()

new Date(0)

new Date(1000*60)

new Date("2018-5-1")

typeof new Date("2018-5-1")

+ new Date("2018-5-1")

typeof + new Date("2018-5-1")

new Date("2018/05/01") db.employee.insertOne({"Time":new Date("2018/05/01")

})

var result = db.employee.findOne({"Time":new Date("2018/05/01")

})

result._id

typeof result._id

result.Time

typeof result.Time

new Date("2018/05")

結論

MongoDB的設計允許document有不同的schema，以及value允許object、array，使儲存結構更為自由。但是，實務上若真的將schema設計的不一樣，這對於DB後續的使用是非常不方便的，所以我們是利用他自由，但仍要加上規範。意思就是在一個collection中我們還是會使用相同的schema，不然也是很難用。

這篇文章說明了MongoDB的基本特性、安裝、CRUD的做法，以及數據類型。但這裡還沒提到的是一些較複雜的篩選方式，以及詳細連線到driven的方式。後幾篇再整理。