# 第零週 - mongoDB 前置教學
# 安裝 mongodb
## 前置環境安裝
* [mongo 安裝](https://www.mongodb.com/try/download/community)
* [compass 安裝](https://www.mongodb.com/try/download/compass)
## driver 介紹
1. [mongoDB 官方文件](https://docs.mongodb.com/manual/core/document/)
2. [.NET Core](https://docs.microsoft.com/zh-tw/aspnet/core/tutorials/first-mongo-app?view=aspnetcore-6.0&tabs=visual-studio)
3. [Node.js NPM Mongoose](https://mongoosejs.com/docs/api/model.html#model_Model.findOne)
## 如何開啟一個 mongo 資料庫
1. 新增 data 與 log 資料夾
2. 指行指令:`mongod --dbpath "data 資料夾"`
3. 若要有 log: `mongod --dbpath "DB資料夾路徑" --logpath "LOG資料夾路徑/mongo.log"`
```
mongo 與 mongod 指令差異
1. mongod:server 端開啟伺服器應用
2. mongo: 客戶端,直連造訪您開啟的 server 應用
```
## 常見指令
## 資料庫顯示
- 顯示資料庫:show dbs
- 切換資料庫:use `資料庫名稱`
- 觀看指令資料庫裡面的集合:show collections
### 新增一筆資料 insertOne
```jsx
db.rooms.insertOne(
{name:"單人房",price:1000,rating:4.5}
)
```
### 新增多筆資料 insertMany
```jsx
db.rooms.insertMany(
[
{
"rating": 4.3,
"price": 1500,
"name": "豪華單人房"
},
{
"rating": 4.8,
"price": 2000,
"name": "雙人房"
}
]
)
```
### 尋找集合裡面的資料 db.collections.find()
```
## 一般搜尋
- db.集合名稱(collections name).find()
- 尋找對應屬性:db.collections.find({屬性名稱:屬性值})
- 模糊搜尋:db.rooms.find({"name":/雙/})
- 數值區間:db.collections.find({屬性名稱:{$lte:400}})
- 複合條件:db.collections.find({屬性名稱:{$lte:400},rating:{$gte:4.8}})
## 常用語法
- project 保護欄位:db.rooms.find({"name":/雙/},{"_id":0})
- 搜尋陣列裡面的值:db.rooms.find({"payment":{$in:["信用卡"]}})
```
| $eq | 等於 |
| --- | --- |
| $ne | 不等於 |
| $gt | 大於 |
| $lt | 小於 |
| $gte | 大於等於 |
| $lte | 小於等於 |
| $in | 存在某個值 |
| $nin | 不存在某個值 |
邏輯運算子:or 或 and
- `$or:find({$or:[{},{}]})`
```=javascript
db.rooms.find(
{ $and:
[
{price:{$lte:1500}},
{rating:{$gte:4.5}}
]
}
)
```
## 修改 updateOne
`replaceOne()`,只能替換整個文件,`updateOne()`則允許更新欄位。
```jsx
db.rooms.updateOne(
{"_id":ObjectId("621edf99a20aa7506a116f9a")}
,{$set:{name:"修改雙人房"}})
```
### 修改多個值 [updateMany](https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/)(filter 篩選 >$set 更換設定)
```jsx
db.rooms.updateMany(
{rating:{$gt:4.5}},
{$set:{price:300}}
)
```
### 替換整個文檔:replaceOne、replaceMany
**db.collection.replaceOne(filter, replacement, options)**
```jsx
db.rooms.replaceOne(
{"_id":ObjectId("621edf99a20aa7506a116f9a")},
{name:"yes~"})
```
### 刪除多個文件:deleteMany(filter)
```jsx
db.rooms.deleteMany(
{
rating:{$gte:4.3}
})
```
## 資料集
``` =JavaScript
[
{
"rating": 4.5,
"price": 1000,
"name": "標準單人房",
"payment":["信用卡","ATM"]
},
{
"rating": 4.3,
"price": 1500,
"name": "豪華單人房",
"payment":["信用卡","ATM"]
},
{
"rating": 4.8,
"price": 2000,
"name": "標準雙人房",
"payment":["信用卡","ATM"]
},
{
"rating": 4.7,
"price": 2500,
"name": "豪華雙人房",
"payment":["ATM"]
},
{
"rating": 4.0,
"price": 3000,
"name": "標準四人房",
"payment":["現金"]
},
{
"rating": 3.5,
"price": 10000,
"name": "總統套房",
"payment":["現金"]
}
]
```
## 第一週主線任務範圍
1. [篩選功能:query-selectors](https://docs.mongodb.com/manual/reference/operator/query/#query-selectors)
2. [輸出結果設定:Projection Operators](https://docs.mongodb.com/manual/reference/operator/query/#projection-operators)
```
find 語法有兩個參數(parameter),分別是 Query 和 Projection,兩個非選填,如果都不設定,
1. 顯示全部:db.集合名稱(collections name).find()
2. 顯示第一個符合條件:db.collections.findOne()
`db.collection.find({price:{$gt: 3000}, {title:1})`
```
3. [Comparison](https://docs.mongodb.com/manual/reference/operator/query/#comparison):價格在 2000 以上的房子
4. [Logical](https://docs.mongodb.com/manual/reference/operator/query/#logical):[$and](https://docs.mongodb.com/manual/reference/operator/query/and/#mongodb-query-op.-and),價格在 3000(含)以下,評價在 4 分以上的房型
5. [Projection Operators](https://docs.mongodb.com/manual/reference/operator/aggregation/project/#mongodb-pipeline-pipe.-project):只顯示價格,不顯示評價
6. [Cursor Methods](https://docs.mongodb.com/manual/reference/method/js-cursor/):
* limit:一頁顯示 N 筆
* skip:跳過幾筆
* count:計算總數量
* size:計算總數量,但會包含 limit、skip
* pretty:程式碼簡化
## 第一週主線任務
### 前置作業
1. 請建立一個 database,並建立一個 `posts` collection
2. 將此 [JSON 資料](https://drive.google.com/file/d/1VCuWX2M6K-Du8pWlrcGImO_ux4Zwsa6v/view?usp=sharing),透過 Compass 倒入到 `posts` collection
```
貼文集合欄位介紹
- name:貼文姓名
- imageUrl:貼文圖片
- content:貼文內容
- likes:按讚數
- comment:留言數
- createdAt:發文時間
- type:貼文種類[fan(粉絲)、group(社團)]
- tags:貼文標籤
```
## 題庫
### 課程範圍
1. 搜尋 name 欄位為 "Ray Xu" 的 document 列表
``` =JavaScript
db.posts.find({"name":"Ray Xu"})
```
2. 新增一筆 document,欄位皆必填
3. 新增多筆 document,欄位皆必填
4. 修改一筆 document,filter 條件請用 `_id` 指定其中一筆資料,`content` 欄位調整為`測試資料`
5. 修改多筆 `name` 欄位為 `"Ray Xu"` 的 document 列表,`content` 欄位都調整為`哈哈你看看你`
6. 刪除一筆 document,filter 條件請用 `_id` 任意指定其中一筆資料
7. 刪除多筆 document,filter 條件請用 `type` 為 `group` 的值,刪除所有社團貼文
8. 刪除多筆 document,filter 條件為以下條件
a. `name`:`Ray Xu`
b. `likes`: 500(含) 個讚以下
9. 查詢全部 `post` 的 document 列表
10. 關鍵字搜尋 `name` 裡面含有 `o` 的 docuemnt 列表
11. 查詢`name` 欄位為 `"Ray Xu"` ,filter 篩選出介於 500~1000(含) 個讚
12. 查詢 `comment ` 有超過 500(含)以上的 document 列表
13. 查詢 `tag` 欄位,有 `謎因` **或(or)** `幹話` 的 docuemnt 列表
14. 查詢 `tag` 欄位,有 `幹話` 的 docuemnt 列表,需隱藏 `_id` 欄位
15. 請嘗試用 Mongo Shell 指令刪除全部 Documents
### 自主研究題
1. posts 所有 document 數量為?(回傳數字)
``` =JavaScript
db.posts.find().count()
```
2. 請查詢 `name` 為 `Ray Xu` 的 document 列表,排序為由新到舊
3. 請查詢 `name` 為 `Ray Xu` 的 document 列表,顯示前 30 筆資料
4. 請查詢 `name` 為 `Ray Xu` ,顯示100(含) 個讚以上的前 30 筆 document 列表,時間排序由新到舊
5. 請查詢 `comment` 超過 `100` 的 document 列表,跳過前 30 筆資料,再顯示 30 筆資料
6. 尋找超夯熱門貼文,請查詢 `likes` **且(and)** `comments` 都超過 `1,500(含)` 的 document 列表
7. 尋找普通熱門貼文,請查詢 `likes` **或(or)** `comments` 超過 `1,000(含)` 的 document 列表
8. 查詢 `image` 欄位為 `null` 的 document 列表
9. 隨意找一筆 document 資料,將 `tag` 欄位裡的陣列,新增一個新 tag 為 `遊記`
10. 將所有 `tag` 陣列裡的 `感情` 都移除