Analysis OpenData with React & MongoDB

許銘仁
9 min readAug 28, 2019

--

最近有點時間,就開始在找些事情做,就想起一些以前想學的技術,也就是標題提的兩種技術,React 與 MongoDB 啦~

所以我透過 OpenData 的資訊,藉由 React、Nodejs 與 MongoDB 來做成一個網站。

記錄一些過程中我所學到與了解的相關資訊,不然之後跑去玩其他東西,又會忘光光 QQ

結論

  1. React → 對於我來說,一開始入門覺得還可以,不會到非常困難,但是當學到一定程度後,難度直接飆升…,所以在寫 Frontend UI 時,每一步都要想 React 如何運作,當寫完時,其實感覺我用到的 React 技術也才一點皮毛,真D難。
  2. Nodejs → 利用 Nodejs 當作後端,作為與資料庫溝通的橋樑。
  3. MongoDB → 除了儲存 OpenData 即時資訊,也會記錄歷史資料。

最後看了收集的一堆歷史資料,可以觀察到每個停車場的生態嗎?

看幾個例子

  • 桃園縣公有府前地下停車場

可以看到平均剩餘車位從 7:30 am ~11:00 am ,車位持續下滑,代表這是一個停車場附近,應該是商業區 (因為一到五上班時段,車位幾乎都滿的,但是假日卻沒有多少車會停這個停車場)。

  • 瑞塘停車場

可以看到平日的平均剩餘車位從 7:30 am ~5:30 pm ,車位都剩很多,然而晚上卻十分稀少,代表這是一個停車場附近,應該是有很多住家或是社區把車輛放置在這個停車場。

成果

Demo

專案製作過程

1. React

先從 React 講起好了,我這邊是利用 npx create-react-app my-app 作為我專案的開始,透過指令即可以建立一個簡易的 React 專案。

前端的部分我是採用 React 來撰寫前端,後端的部分則是使用 Nodejs。

因為這邊專案的 React 是依靠 npm start 來啟動,所以這邊我將 Nodejs 的啟動指令也加入到 npm start ,不然每次都要分開啟動很麻煩。

使用 concurrently 去執行多種命令,讓前後端依序啟動。

到 package.json 裡面的 scripts/start 新增命令

"start": "concurrently \"command1 arg\" \"command2 arg\""For Example :
"start": "concurrently \"node server.js\" \"react-scripts start\""

再來是 Component lifecycle,必須先要搞懂 Component 調用的順序,不然根本不知道數值要放在才能夠將想要的 Component render 出來

constructor() --> render() --> componentDidMount()

constructor() → 通常是當你要設定 state 或是 綁定方法才要撰寫

render() → 畫畫囉 (每個 Component 都必須要寫的)

componentDidMount() → 當元件創建好時,會立即呼叫這一個函式,你可以在這邊用 fetch 等方式,獲得遠端資料來,更新你 Component 內的資料,也可以呼叫 setState 來重新繪畫你的 render 內容。

componentDidUpdate() → 當元件的發生變化,會立即更新,在初次 render 時,不會呼叫這方法。通常是用來更新 render 的方法,可以透過讀取 prevProps, prevState 這兩個傳入的值,來看元件相關資料(props, state, …)與先前狀態有沒有不同,來作為對元件進行更新的依據。

其中我有使用許多網路上寫的元件,再將其做調整成我理想的元件,像是 google map 與 liquid gauge 等等…,讓網頁不要看起來那麼單調 (還是很醜,反正只是學技術!?),會附在下面的相關資料中。

Note-1

Button OnClick 在 React 中十分常見,假設你要在點擊後執行任何的 console 或函式,不能直接寫 OnClick={this.Func();},這樣會在創建該 Button 元件時,就直接觸發了。

Notice how with onClick={() => alert('click')}, we’re passing a function as the onClick prop. React will only call this function after a click.

要改用 OnClick={() => this.Func()}這樣 React 才會在你點擊後去查看這一個函式。

Note-2

對於 Component 何時需要撰寫 Constructor,只有當需要初始化 Component 的狀態才需要用到,如果是單純父元件傳入 props 的話,是可以不用撰寫 Constructor 的。

If you don’t initialize state and you don’t bind methods, you don’t need to implement a constructor for your React component.

2. MongoDB

MongoDB 這邊主要紀錄查看工具與查詢方法。

一開始使用 MongoDB 要去看他的資料,不太喜歡用那個 cmd 的背景去看,真D醜,所以就選了一個 GUI 工具可以輕鬆地去看資料:RoBo 3T

一個給 MongoDB 的 GUI 工具,使用起來還可以。

語法的部分,因為我是透過 Nodejs 去與 MongoDB 溝通,所以是用 Javascript 撰寫。

一般查詢應該都沒什麼問題,不過我的資料裡面是擁有 Nested json,長這樣:

{
'someKey': 'someValue',
'array' : [
{'name' : 'test1',
'value': 'value1'
},
{'name' : 'test2',
'value': 'value2'
}
]
}

這邊 find({“array.name”: “test1’’}) 就會回傳找到的那一筆資料,只有在這邊遇到點問題,其他 MongoDB 的查詢與儲存基本應該都沒什麼問題。

喔對~我在讀取歷史資料時,回傳資料超過一百筆,結果 MongoDB 就出錯了

所以我在查詢歷史資料時,會將 db.close() 在查詢完後立即關閉,這樣更改後,就沒有再出錯了。

雖然花了一個多禮拜,收集歷史資料很耗時 QAQ,能簡單的做一個簡易的小專案,滿好玩的。

最後也有將專案部署到 google cloud platform,透過 docker 將專案架起來 (也沒人會來看這些資料吧,過個一兩天把它關掉 QQ)

下一個來玩一下自動化部署與監控好了,不然每次都要上 VM 重新手動更新與部署自己寫的專案,然後還要在那邊 docker logs 很累的呢~

GitHub 連結

相關資料

--

--