2017年12月15日 星期五

MongoDB 筆記 (三) : update / replace

要改野, 最直接就更係諗到 update 喇, 不過 update 同 insert 一樣, 都有幾款, 另外仲有個 replaceOne.


  • db.collection.update()
  • db.collection.updateOne()
  • db.collection.updateMany()
  • db.collection.replaceOne()

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>,
     collation: <document>
   }
)
update 真係要好小心, 就咁睇好簡單, 比個 query 佢 update 就得.
比如話, 要將 Super169 既身高改為 167, 好直接會咁寫吧:

db.user.update({id:"Super169"},{height:167})
咁你就出事了.....之後 Super169 既 document 就咁無左, 得番 一份 {heigth:167} 既 document.
因為佢既 update, by default 係去 replace 成張 document.

要做到想要既 update, 就要加多個 $set 既 operator:

db.user.update({id:"Super169"},{$set: {height:167}})
真係幾危險架, 因為一張 document, 入面可以裝住成大抽野, 一下就無左, 真係唔知點算.

MongoDB 筆記 (二) : find



find() - 應該係最常用既 method 了

query:  一個 JSON object 去比 condition
projection: Define 個  output 既 file list

講都唔易, 用例子最實際, 全部用 user collection 去玩:

1) 搵哂全部人:
  • db.uesr.find()
2) 搵個 id 係 Super169 既:
  • db.user.find({id : "Super169"})
3) 搵個 height 大於 160 既:
  • db.user.find({height : { $gt : 160 }}) 
4) 搵個 height 大於 150 但又不超過 165 既:
    • db.user.find({height : { $gt : 150, $lte : 165 }})
    5) 搵個 weight 最少 50, 而 height 不超過 150:
        • db.user.find({ $and: [{weight : {$gte:50}}, {height : { $lte : 150 }}]})
        6) 搵 Super167 同 Super169:
            • db.user.find({ id : { $in : ["Super167","Super169"] }})
            7) 搵 ..... 咁多野搵, 自己試下喇.  黎黎去去, 都係 $and, $or, $gt, $lt, .... 呢D野, 試多D就得.

                仲有個好好玩既, 在 find(...) 之後, 加個 .pretty(), 就會 return format 左既 JSON object.

                例如:

                • db.user.find({id : "Super169"}).pretty()


                不過, 純粹自己 check 果陣易睇, program 入面就無謂浪費了.



                MongoDB 筆記 (一) : insert

                識搵野唔識入野都無用, MongoDB 入野, 有幾個方法:


                • db.collection.insert()
                • db.collection.insertOne()
                • db.collection.insertMany()

                db.collection.insert(
                   <document or array of documents>,
                   {
                     writeConcern: <document>,
                     ordered: <boolean>
                   }
                )
                可以用黎加一份 document (可以睇成係一隻 JSON record), 或者成個 array 既 documents

                例如:
                • db.sample.insert({user:"Super169"})
                • db.sample.insert([{user:"Super167"},{user:"Super168"},{user:"Super169"}])


                writeConcern 比較複雜, 我自己都唔係好明, 有興趣自己睇喇, 平時我都唔用(應該係唔識用).


                db.collection.insertOne(
                   <document>,
                   {
                      writeConcern: <document>
                   }
                )
                唔駛多講, 只可以 insert 一份 document, 唔可以成個 array 比佢.

                例如:
                • db.sample.insertOne({user:"Super169"})

                db.collection.insertMany(
                   [ <document 1> , <document 2>, ... ],
                   {
                      writeConcern: <document>,
                      ordered: <boolean>
                   }
                )
                同 insertOne 對著幹, 只可以成個 array 比佢, 唔可以單獨一份 document.
                不過, 個 array 入面可以只係得一份 document....甚至無野.

                例如:
                • db.sample.insertMany([{user:"Super167"},{user:"Super168"},{user:"Super169"}])


                insert, insertOne 同 insertMany 有乜分別?

                無事無幹, 對個 collection 而言, 係無分別既, 你可以用哂 insert 唔駛煩.
                不過, 佢地既 return object 就有 D 唔同, 你要做 error handling, 就要識分.

                例如:

                • db.sample.insert({user:"Super169"})
                WriteResult({ "nInserted" : 1 })
                • db.sample.insertOne({user:"Super169"}) 
                {        "acknowledged" : true,        "insertedId" : ObjectId("5901a950276033a2cfe79009")}

                • db.sample.insert([{user:"Super167"},{user:"Super168"},{user:"Super169"}])
                BulkWriteResult({
                        "writeErrors" : [ ],
                        "writeConcernErrors" : [ ],
                        "nInserted" : 3,
                        "nUpserted" : 0,
                        "nMatched" : 0,
                        "nModified" : 0,
                        "nRemoved" : 0,
                        "upserted" : [ ]
                })
                • db.sample.insertMany([{user:"Super167"},{user:"Super168"},{user:"Super169"}])
                {
                        "acknowledged" : true,
                        "insertedIds" : [
                                ObjectId("5901a9e9276033a2cfe7900d"),
                                ObjectId("5901a9e9276033a2cfe7900e"),
                                ObjectId("5901a9e9276033a2cfe7900f")
                        ]
                }
                至於用邊個, 睇下你自己想點了.  insert 完想攞番個 key 去再做野, 就用 insertOne 或者 insertMany, 否則, insert 完知道得唔得就夠, 用 insert 就可以了.


                MongoDB 筆記 (序)

                學新野, 當然要記低 D 重點, 不斷重溫, 直到入哂腦..

                MongoDB 同以往用開既 SQL Server 其實真係好唔同, 好多野唔可以用 relational database 去諗.
                要慢慢改變自己諗野既方式, 而且, 我都唔係好肯定, 自己學到既有無錯, 仲要慢慢研究.

                有乜野想查, 最直接就係去官網睇  MONGODB MANUAL


                首先, 有幾個重要指令, 有用得黎有應該唔會常用:

                • show dbs -  顯示 server 上有既 db 
                • use <db> - 同 SQL server 一樣, 轉去指定既 db
                • show collections - 顯示 現在的 db 上的 collection 
                • db.<collection>.drop() - 成個 collection 剷走佢
                • db.stats() - 睇下 db 既資料
                • db.<collection>.status() - 睇下 collection 既資料
                以上都同 data 無乜大關係, 一般我地最常做既, 不外乎 insert, retrieve, update, delete:


                2017年5月17日 星期三

                NodeMCU

                買左 ESP8266, 一直都係當 Arduino 用, 但好多人講到 NodeMCU 好好, 又手痕試下.
                先至聲明, 我本身乜都唔識架, 睇完唔好信哂....

                1) 首你, 根據你塊板, 要裝左 USB-TTF 芯片既 driver (例如 CH34X, CP210X,...).
                    我自己用開 CH34X 既 (勝左夠 cheap), 一直裝左

                2) 下載 ESPlorder, 自己部機要有 JAVA SE7 或以上至用到.
                     下網地點: https://esp8266.ru/esplorer/#download

                3)   爆開個 zip, 執行 ESPlorer.bat, 就會見到差唔多既畫面 (depend on ESPlorer 既版本).

                選好個 port (例如我係 port 29) 同埋 baudrate (比如 115200), 就可以試下 [Open] 去連線了.

                弊.....連唔到既?

                更係喇, 你都未裝 NodeMCU 去塊 ESP8266 度.

                4) 去舊雲度 build 左個 firmware 先.  https://nodemcu-build.com/
                    由於每個 modules 都要食位既, 所以自己按需要執你既野.  今次執漏左唔緊要, 隨時上黎再執過再 flash 一次就得.


                     填好自己既 email. 就可以 轆去底,  [Start your build], 之後就等 email.

                5)  之後會收到一個標題係 "NodeMCU custom build started" 既  email, 即係話收到 request 做緊野.   等多陣, 就會有個標題係 "NodeMCU custom build finished" 既 email, 即係攪掂.  要等幾耐?  唔駛好耐, 幾分鐘就得.
                     入面會有條 link, 比你 download 個 firmware, 一個係 float 一個係 integer, 同埋會講比你聽, 你選左乜野.
                記住, 24小時內要去 download, 如果唔係....咪再 build 過囉.

                6) 有 firmware 又點, 你都要識得 flash 入去至得架.
                     首先 make sure 你部機網左 python, 同埋 pip, 直接行  pip install esptool


                記住, 如果有 proxy 既就先行左至可以 download 到野:

                  set HTTP_PROXY=http://<user>:<pwd>@<server>:<port>
                  set HTTPS_PROXY=http://<user>:<pwd>@<server>:<port>

                Install 完 esptool, 你就可以直接執行 esptool.py 了 (佢放左入 python 既 executables folder)

                7) 刷 firmware:

                  esptool.py --port <serial-port-of-ESP8266> write_flash -fm <mode> 0x00000 <nodemcu-firmware>.bin

                mode is qio for 512 kByte modules and dio for >=4 MByte modules (qio might work as well, YMMV).

                例如:

                  esptool.py --port com29 write_flash -fm dio 0x00000 nodemcu-master-10-modules-2017-05-18-02-57-33-integer.bin

                之後就等佢 flash 喇:


                攪掂, 可以去試了.

                8) 再 [Open] 多次睇下:
                仲係咁既?  唔係呀嘛.



                唔知係咪有 D 野唔同左, 一開始佢認唔到個 Firmware, 又或者個 firmware 唔識 response.
                只要你是旦叫佢 send D 野, 等佢比 reply 就得.
                雖然你唔可以 "Send to ESP", 不過, 好在個 ESPlorer 左右唔夾既, 左邊一定要 connect 左至比你 send, 右邊可以未 connect 到就去 check.  所以, 你只要 check 下個 Heap 就得了.

                唔髮理果句,
                Can't autodetect firmware, because proper answer not received (may be unknown firmware).
                Please, reset module or continue.

                希望將來可以一按個 open, 自己 send D野去 check (可能家陣都有, 不過唔夾), 就可以認到了.

                9) 開到之後, 就可以試下係咪行到 lua script 了, 慣性整句 Hello World 就收工喇:
                左邊輸入  print("Hello World!")  然後按  [Send to ESP], 之後右邊就出番 Hello World!, 攪掂.





                2017年5月15日 星期一

                ESP32

                都唔知關唔關事了, 見 ESP32 比 ESP8266 更強勁, 就買左粒黎玩下.

                我買既, 只係 cheap cheap 既  Goouuu-esp32 版本.

                Goouuu-esp32
                底版既針腳: 

                Pin Mapping 呢樣最緊要知


                Arduino IDE 開發 ESP-32, 由於仲未有 registry 直接下載安裝, 只可以手動:

                1) 去 arduino.cc 下載並安裝 Arduino IDE 

                2) 安裝 Python 2.7

                3) 去 github 既 espressif arduino-esp32 下載 [Clone or download] -> [Download Zip]

                用 installer 既可以跟 Windows 教學, 如果用 Zip 爆 Arduino IDE 既, 就要自己黎了.

                4) 將 espressif arduino-esp32 個 master zip 爆去  Arduino IDE 既 folder 下面.  可以在 hardware 之下, 先開個 espressif 既 folder, 再加個 esp32, 然後爆哂入去.
                比如我個 Arduino IDE 爆左去 "E:\Arduino\IDE\arduino-1.8.2" 果度, 咁個 esp32 既 master zip 入面既野就放 E:\Arduino\IDE\arduino-1.8.2\hardware\espressif\esp32 (唔要 zip file  arduino-esp32-master 果層)

                5) 開 command prompt 走去 esp32 下面既 tools folder
                6) 如果有  proxy 既就先設定:
                    SET HTTP_PROXY=http://<user>:<passwod>@server:port
                    SET HTTPS_PROXY=http://<user>:<passwod>@server:port
                7) 之後執行 get.exe, 如果成功會見到咁既 message:

                8) 跟住開  Arduino IDE, 去睇下 Tools->Board 入面, 應該加左 ESP32 Arduino 既 board 了, 咁就可以選番你塊版, 準備開始 program 了.




                2017年3月22日 星期三

                2017 又再 IoT: NodeJs + Mosquitto + MongoDB 簡單測試

                好喇, 已經裝左 mosquitto, MongoDB 同埋 nodejs, 家陣仲係唔知發生乜事.
                不過, 先做個簡單測試, 睇下 work 唔 work 先.

                1) mosquitto - 可以用 chrome apps: MQTTLENS, 又或者 mqtt_spy

                2) mongoDB - 可以起左 server 後 執行 mongo.exe 直接連上 MongoDB

                3) 裝先行到  node 或者 npm 都應該得掛.
                    再唔係可以試下呢個 script, 用 node example.js 去行, 佢會起左個 web server.
                    用 browser 開 localhost:3000 應該見到句 Hello Work 就係得了.

                const http = require('http');
                const hostname = '127.0.0.1';
                const port = 3000;
                
                const server = http.createServer((req, res) => {
                  res.statusCode = 200;
                  res.setHeader('Content-Type', 'text/plain');
                  res.end('Hello World\n');
                });
                
                server.listen(port, hostname, () => { 
                  console.log(`Server running at http://${hostname}:${port}/`);
                });
                
                 4) 最後, 更係要試下 3 件野係咪夾得埋黎用, 如果唔係, 裝黎托咩.
                     可以做個簡單既測試:

                • 用 nodejs 起個 process
                • 睇住 mosquitto 既 message
                • 收到想要既 message 就儲入 MongoDB
                    是旦搵個 folder, 安裝 nodejs 定所需既野.  今次只係要 mqtt 同 mongdb
                    比如開個新 folder, E:\Node\Tester, 然後走去 E:\Node\Tester 行呢句野:
                npm install mqtt mongdb
                    佢就會裝左 mqtt 同 mongdb 既 package 去 E:\Node\Tester\node_modules
                    之後就開個 text file 叫 example.js copy 呢堆野入去:

                consoleLog('MQTT MongoDB Tester Started');
                var mqtt=require('mqtt');
                var mongodb=require('mongodb'); 
                var mongodbClient=mongodb.MongoClient; 
                var mongodbURI='mongodb://localhost/data';
                var deviceRoot='mqtt/demo/';
                var collection,client; 
                 
                mongodbClient.connect(mongodbURI, setupCollection);
                 
                var connInfo = {
                  host: 'localhost',
                  port: 1883,
                  clientId: 'guest169'
                }
                 
                function strNow() {
                  return (new Date()).toISOString().replace('T',' ').replace('Z','');
                }
                
                function consoleLog(msg) {
                  console.log(strNow() + ' : ' + msg);
                }
                
                function setupCollection(err,db) { 
                  if(err) throw err;
                  collection=db.collection('mqtt_demo');
                  client=mqtt.connect(connInfo)
                  client.subscribe(deviceRoot + '#')
                  client.on('message', insertEvent);
                }
                
                function insertEvent(topic,payload) { 
                  var now = strNow();
                  var key=topic.replace(deviceRoot,'');
                  console.log('%s : [%s] - %s', now, key, payload);
                  collection.update( 
                    { _id:key },
                    { $push: { events: { event: { value:payload, when:new Date() } } } },
                    { upsert:true },
                    function(err,docs) {
                      if(err) { consoleLog('#### Insert fail'); }
                    }
                  )
                }
                

                    然後行 node example.js 就可以了.
                    之後, 用  mqtt_spy 或者  MQTTLENS 去 publish, 個 topic 如果開頭係  "mqtt/demo/" 就會接收, 然後放入 MongoDB.  只要走去 MongoDB, use data, 再 show collections, 應該會見到 mqtt_demo 既, 然後再db.mqtt_demo.find(), 就會見到收左乜野了.