# Deno 與 MongoDB 共舞

### 開始之前： 設定 collection 以及 database

繼昨天的安裝教學，我們現在來建立待會要使用的 database 以及 collection ：

1. 打開 MongoDB Compass 並按下 `Create Database` 。

![https://ithelp.ithome.com.tw/upload/images/20201019/20110850Ld4emQn82M.png](https://ithelp.ithome.com.tw/upload/images/20201019/20110850Ld4emQn82M.png)

1. 輸入 Database 和 Collection 的名字：

![https://ithelp.ithome.com.tw/upload/images/20201019/20110850kypRBuvnW1.png](https://ithelp.ithome.com.tw/upload/images/20201019/20110850kypRBuvnW1.png)

1. 創建完成，如果讀者有需要，也可以先插幾筆資料進去。

![https://ithelp.ithome.com.tw/upload/images/20201019/201108504Eab6kIbd1.png](https://ithelp.ithome.com.tw/upload/images/20201019/201108504Eab6kIbd1.png)

### 進入正題： deno\_mongo 教學

`deno_mongo` 是一款 MongoDB 資料庫驅動的 Deno 第三方套件，它是基於 rust 官方的 mongoldb Library 所打造的。

#### 建立連線

在開始之前，需要將第三方模組引入：

```
import { MongoClient } from "https://deno.land/x/mongo@v0.13.0/mod.ts";
```

引入後，將 `MongoClient` 物件實例化：

```
const client = new MongoClient();
```

開啟 MongoDB 後，就可以使用 `client` 建立連線：

```
client.connectWithUri("mongodb://localhost:27017");
```

執行到這一步時，就已經成功連上 MongoDB 了，不過我們還沒告訴 Deno 要存取資料庫中的哪一個 database 和 collection ：

```
const db = client.database("test");
const users = db.collection("users");
```

上面的範例是讓 Deno 連上 MongoDB 中 `test` database 的 `users` collection 。

#### 使用 Interface 防止非預期資料寫入 MongoDB

使用 Interface 可以有效預防有心人士在 json 格式內插入不需要的資料。

假設我們預期 collection 的欄位只有 `id` 、 `username` 以及 `password` ，可以先定義好 interface ：

```
interface UserSchema {
  _id: { $oid: string };
  username: string;
  password: string;
}
```

定義好後，我們在連結 collection 的那行程式碼加入 interface 檢查：

```
const db = client.database("test");
const users = db.collection("users");
```

### 常見操作

在學會如何與 MongoDB 建立連線後，跟著筆者一起看看 deno\_mongo 提供的操作方法吧！

> 注意！進行以下常見操作都需要先將 Deno 與 MongoDB 做連接唷！
>
> ```
> import { MongoClient } from "https://deno.land/x/mongo@v0.13.0/mod.ts";
> const client = new MongoClient();
> client.connectWithUri("mongodb://localhost:27017");
> const db = client.database("test");
> const users = db.collection("users");
> ```

#### 新增單筆資料

```
const insertId = await users.insertOne({
  username: "user1",
  password: "pass1",
});
```

#### 新增多筆資料

```
const insertIds = await users.insertMany([
  {
    username: "user1",
    password: "pass1",
  },
  {
    username: "user2",
    password: "pass2",
  },
]);
```

#### 尋找單筆資料

```
const user1 = await users.findOne({ _id: insertId });
```

#### 尋找多筆資料

```
const all_users = await users.find({ username: { $ne: null } });
```

#### 計數

計算 Collection 中有多少筆資料包含使用者輸入的鍵值對 ：

```
const count = await users.count({ username: { $ne: null } });
```

#### 聚合

聚合操作主要用於處理數據 (像是：取平均值、加總等操作)並回傳計算後的結果。

```
const docs = await users.aggregate([
  { $match: { username: "many" } },
  { $group: { _id: "$username", total: { $sum: 1 } } },
]);
```

#### 新增單筆資料

```
const { matchedCount, modifiedCount, upsertedId } = await users.updateOne(
  { username: { $ne: null } },
  { $set: { username: "USERNAME" } }
);
```

#### 新增多筆資料

```
const { matchedCount, modifiedCount, upsertedId } = await users.updateMany(
  { username: { $ne: null } },
  { $set: { username: "USERNAME" } }
);
```

#### 刪除單筆資料

```
const deleteCount = await users.deleteOne({ _id: insertId });
```

#### 刪除多筆資料

```
const deleteCount2 = await users.deleteMany({ username: "test" });
```

#### 跳過

我們可以使用 `skip()` 跳過指定數量的資料：

```
const skipTwo = await users.skip(2).find();
```

#### 限制

如果使用者需要在 MongoDB 中找尋數據並指定數據記錄的數量，可以使用 `limit()` ：

```
const featuredUser = await users.limit(5).find();
```

### 執行

最後要注意的是， `deno_mongo` 目前還不穩定，使用上不要忘記加入 `--unstable` 標籤唷！

```
deno run --allow-net --allow-write --allow-read --allow-plugin --allow-env --unstable yourCode.ts
```

### 總結

本篇文章提到了如何使用第三方套件去連線 MongoDB 。明天筆者就會將簡易 WebAPI 留下的坑填完，順便分享一下什麼是 ORM ，我們明天見！

> 此外，本篇所使用的範例程式碼參考了 [deno\_mongo](https://deno.land/x/mongo@v0.13.0) 的官方文件，請知悉。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ianchen0119.gitbook.io/deno/shi-yong-deno-da-zao-web-api/shi-yong-deno-chuan-jie-mongodb.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
