這篇文章主要是介紹以C#強型別使用Mongodb driver連線的CRUD語法,一些MongoDB的名詞就不會多著墨。

情境

我們要建立一個 hellomongodb 的資料庫,裡面有 users 的 collection,存放 user 的相關資訊。
以下範例都會使用非同步的方式,若有需要同步執行的,可以自行移除async看看,大致上都是這樣。

先打開shell模式建立DB與collection

1
2
3
4
//切換至 hellomongodb 資料庫
use hellomongodb
//建立名為 users 的 collection
db.createCollection("users")

建立連線

1
2
3
4
5
6
const string MongoAddress = "mongodb://localhost:27017";
const string HelloDatabase = "hellomongodb";
const string UserCollection = "users";

var client = new MongoClient(MongoAddress);
var collection = client.GetDatabase(HelloDatabase).GetCollection<UserEntity>(UserCollection);

Create

剛開始肯定沒有資料的,所以我們會先建立幾筆資料做為測試

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//建立一筆資料
private static async void CreateUser()
{
await GetUsersCollection().InsertOneAsync(
new UserEntity{ Name = "Shaka", Country = "Unknown", City = "Zodiac Temple"}
);
}
//一次建立多筆資料
private static async void CreateMultiUsers()
{
await GetUsersCollection().InsertManyAsync(new List<UserEntity>
{
new UserEntity{ Name = "Jack", Country = "Taiwan", City = "Taipei"},
new UserEntity{ Name = "Sion", Country = "Unknown", City = "Underworld"},
new UserEntity{ Name = "Saga", Country = "Unknown", City = "Zodiac Temple"}
}
);
}
Read more »

這邊提幾個基本的查詢容易犯得錯,之後再追加比較進階的部分。

  • 只是要確認存在,讓DB只回覆 _id,不需要整個回覆

常見的

1
2
3
4
db.users.findOne({
'username' : 'pattri'
'pwd' : 'iampass123'
})

其實只要回覆 _id,這樣可以提高傳輸效率

1
2
3
4
db.users.findOne({
'username' : 'pattri'
'pwd' : 'iampass123'
}, { '_id':1 } )
  • 重複用運算子搜索同一個欄位

1
2
3
4
db.users.find({
{ 'age': {'$gte': 30} ,
{ 'age': {'$lte': 40} ,
} )

正確的應該是

1
2
3
db.users.find({
'age': {'$gte': 30, '$lte': 40}
} )
Read more »

最近在使用 docker-compose 加入 mongodb 時遇到一個地雷。由於近日來的挫折感,不免還是問一下專家,專家馬上說道:「對呀!應該要一樣的!」接著馬上解釋原因。是這樣啦~我真的有看過官方文件以及手上的書,也許我沒看得很仔細所以忽略掉吧!

當初在debug時很認真搜尋網路,發現沒找到相關問題,有提到的只有一個網頁,我想這問題應該在本機開發或者只做demo都不會遇到,不過進到產品階段肯定會碰到。

通常我們在本機開發都會用的yml設定如下:

1
2
3
4
5
6
7
8
version: '3'

services:
mongo:
image: mongo
container_name: mongo_container
ports:
- "27017:27017"

啟動後就能很開心的用GUI或cmd連進mongo進行開發。

問題發生在..
開發階段時,我們將mongo綁定了url(當然在hostfile也加了),如下


1
2
3
4
5
6
7
8
version: '3'
services:
database:
image: mongo
container_name: Mongo_DkrCmps_Test
ports:
- "27117:27017"
entrypoint: [ "/usr/bin/mongod","--bind_ip", "localhost,mongo-local-test.com"]

當很開心的啟動後,就發現用任何方式都無法連線到mongo囉!即使docker-compose ps 也可以看到他在listen的狀態,那麼問題是出在哪?

answer

關鍵就是出在 yml 的 service 名稱,這個命名需要和你設定entrypoint 所bind的內容一樣,所以我們來調整一下..

Read more »

macOS的使用者應該都使用過vs code,加上各種plugin做起事來更是如虎添翼。

今天要介紹的工具是Open In Code,此程式的功能就是在Finder上增加一個”使用vs code開啟”的功能,讓你在使用Finder瀏覽時,隨時都能夠使用vs code開啟當前目錄,不需要再辛苦得再選定資料夾開啟。

那馬上就使用Brew cask來安裝吧!

1
brew cask install open-in-code

alt

下載完後會告訴你安裝好了以及相關位置。

  1. 去應用程式裡面找到 Open In Code.app
  2. 點選 Open In Code.app
  3. 按住 cmd拖移到 Finder 上方工具列,出現綠色+號即可。
    這樣就大功告成囉! 以後使用Finder瀏覽時,就能隨時隨地以 vs code 開啟這個目錄了。

alt

Read more »

原本要寫個用 docker compose 來起 MongoDB container 的文章,發現整個弄完不到三分鐘,好像有點過於簡單。
就順便用這個為範本來討論一下port的功能與expose的差異,在剛開始接觸的時候被搞混了一下。

攥寫yml檔案

docker compose的檔案是用yml寫的,如果不知道什麼是 yml,可以參考一下連結,基本上就是比json更高可視化、更簡潔(更小)的設定檔。

將以下內容存成 docker-compose.yml 檔案即可

1
2
3
4
5
6
7
version: '3'
services:
database:
image: mongo
container_name: Mongo_DkrCmps_Test
ports:
- "27117:27017"

執行

下面兩個指令分別就是啟動與關閉這份 docker-compose

1
2
docker-compose up    //啟動
docker-compose down //關閉

alt

上圖就是寫好yml後執行,如果沒有MongoDB的image就會從網路上下載,下載好後就可以看到MongoDB的container已經在運行。

Read more »

今天在做一個需求時,使用 gRPC/protobuf 工具產生 .cs 檔案發現一個小bug,雖然不是很嚴重,不過還是記錄一下。

狀況

  • 條件:.proto 檔案名稱帶有數字、數字後的第一個字母是英文且小寫
  • BUG:產生出來的 .cs 檔名,在數字後的第一個英文字母會強制變成大寫

例如今天建立一個檔案叫做 Number1test.proto 的檔案,經過 gRPC Tool 產生出來的 service 檔案預期會是 Number1test.cs,但結果卻是 Number1Test.cs

注意到了嗎?在 1 後面的 t 應該會是小寫的,卻會變成大寫 T。

原因

強者我同事馬上上github找到這段 source code 並且發現 bug 囉!

在善心人士修復之前就要特別注意這個部分

Read more »

嗯..這篇文章筆記性質很重,因為工作上需要就順便記錄一下流程以及可能遇到的問題。

安裝

1
brew install mongodb

真的就這樣!
好吧!我有先安裝 HomeBrew 這個套件,相信 macOS 使用者應該都知道,這個套件能處理相依性的問題,若有使用linux like 的應該很能體會各種套件相依性的難搞。
BTW,不需要特別先 brew update,因為使用 brew 就會先執行 update 指令囉。

啟動mongodb前準備

MongoDB預設的DB路徑是 /data/db,所以要先配合建立這個資料夾,並賦予權限。

1
2
3
sudo mkdir -p /data/db
sudo chown pattrichou /data/db //pattrichou請自行替換成你的使用者名字
mongod //啟動

小提醒:你可以使用 whoami 指令來查詢使用者名稱

如果你不是想使用預設的路徑,可以透過 –dbpath 參數來指定DB路徑

1
mongod --dbpath <your own path>
Read more »

人的進步始終來自惰性

最近看到同事的一指令同步所有repo覺得很神奇,當時僅有這樣的感覺。後來在工作上一直重複得打一些指令覺得很阿雜,心想為什麼我要一直做這種事情,其實滿腦子根本已經是那個神奇的alias的形狀了,於是我就開始編輯屬於自己的alias囉!

必備工具

zsh
Oh My Zsh(optional)

開始編輯alias

檔案位置在使用者帳號底下,檔名 .zshrc

開啟檔案

我們使用vi指令開啟,並拉到最下面,按下 i 開始編輯

1
# vi ~/.zshrc

這邊其實就已經有給你範例了,把註解#拿掉就是一個別名。
alt

Read more »

軟體架構圖是讓人理解系統非常重要的,而用於表現、體現軟體架構的圖有非常多種,這邊談到的是C4模型。

圖勝表、表勝文

大家都知道圖的重要性,繪製一張好的圖需要很多次的來回討論與修改,儘管花費很多時間,一但完成能夠大幅縮短後人了解系統的時間。

好啊!那來畫UML吧

UML並不是不好,而是有一些限制在,簡單列一下我的感受:

  • 觀看高度不夠。如果是想讓人快速了解系統或是要跟老闆報告,這些圖都不太適合,通常需要其他圖片來輔助。
  • 外行看不懂。圖片畫出來就是要與人溝通的,如果門檻過高讓人看不懂無異於無字天書,如果你的對象是工程師,那我想應該不會有太大問題。
  • 你真的懂UML?UML包含了各種類型的圖,除非有認真學習過怎麼繪製,否則裡面的每個細節可能會被誤用,一但誤用,就是誤會的開始了..
    例如循序圖的 Component/Entity是什麼?何時該用虛線何時該用實線…等等
  • 到底要多詳細?同樣一張圖片,無法有明確的規範到底該畫到多詳細,有的人認為寫出描述即可,有的人需要畫出實作的方法名稱

說了一些點,本篇不是討論UML的,不過我依然認為他還是個對溝通有用的圖,如果真的有寫文件的話,甚至如果真的有人看的話。

C4 Model

最近接觸到C4 Model架構,用來描述軟體架構的概念,當然相同的工具、做法有很多種,這邊就先寫一篇心得來記錄一下。
作者將架構圖的視野由高至低分為四個等級,第一等級是最上層也是最粗略的。

以下圖片街擷取自官網

Read more »

在這個硬體成本不算高的年代,記憶體的使用通常都略微不那麼謹慎;往往在宣告數字型別時不會太謹慎(還是剛好我遇到的都…),例如只有short 需求卻宣告成 int 這種狀況屢見不鮮。

若要好好地控制記憶體使用量,避免溢位的需求就要特別注意,尤其這種狀況通常發生在執行期,log也可能也無法完整紀錄當時狀況,因此 Checked 語法就派上用場了。

1
2
3
4
short shortNumber = 32767;
Console.WriteLine($"Org short number: {shortNumber}");
shortNumber += 1;
Console.WriteLine($"Plus 1 to short number:{shortNumber}");

顯示結果如下:

1
2
Org short number: 32767
Plus 1 to short number:-32768

明明只有加1卻出現了意想不到的數字。為了避免這種情況發生,可以使用Checked語法來做檢查,至少如果有問題會先彈出exception。

1
Console.WriteLine($"Plus 1 to short number:{checked(shortNumber+=1)}");

結果是直接跳出exception並告知以下結果:

1
Unhandled Exception: System.OverflowException: Arithmetic operation resulted in an overflow.

當然我們也可以預先使用try catch來攔截相關的錯誤

Read more »