PythonからMongoDBをCRUD操作

MongoDBはHomebrewで、pymongoはpipでインストールすれば使える。

Create

前半は定型文。 datebaseとcollectionは、client.my_database.my_collectionでも作れる。 でも、のちのち名前を自由に付けたくなると思うのでStringを使った。 データはjsonライクなのをinsert()で書き込む。

>>> import pymongo
>>> client = pymongo.MongoClient('localhost', 27017)
>>> db = client['my_database']
>>> co = db['my_collection']
>>>
>>> data = [
...     {'a': 1, 'b': 2},
...     {'a': 3, 'b': 4, 'c': 5}
... ]
>>> result = co.insert(data)

Read

全データはfind()で取得できる。

>>> data = [d for d in co.find()]
>>> for d in data:
...     print d
...
{u'a': 1, u'_id': ObjectId('57ea7b568365d9a2cf95dfc3'), u'b': 2}
{u'a': 3, u'c': 5, u'_id': ObjectId('57ea7b568365d9a2cf95dfc4'), u'b': 4}

条件指定したい場合は、これもjsonライクに。

>>> print co.find({'a': 1})[0]
{u'a': 1, u'_id': ObjectId('57ea7b568365d9a2cf95dfc3'), u'b': 2}

Update

dictのlistにまたdictを追加したい場合は、再度insert()を使う。

>>> data = [
...     {'a': 6, 'b': 7}
... ]
>>> result = co.insert(data)
>>> data = [d for d in co.find()]
>>> for d in data:
...     print d
...
{u'a': 1, u'_id': ObjectId('57ea7b568365d9a2cf95dfc3'), u'b': 2}
{u'a': 3, u'c': 5, u'_id': ObjectId('57ea7b568365d9a2cf95dfc4'), u'b': 4}
{u'a': 6, u'_id': ObjectId('57ea7b568365d9a2cf95dfc5'), u'b': 7}

置換したい場合はupdate()を使う。 第一引数は条件、第二引数はkeyが'$set'で、valueが置換データのdictを指定。

>>> result = co.update({'a': 3}, {'$set': {'a': 100}})
>>> for d in co.find():
...     print d
...
{u'a': 1, u'_id': ObjectId('57ea7b568365d9a2cf95dfc3'), u'b': 2}
{u'a': 100, u'c': 5, u'_id': ObjectId('57ea7b568365d9a2cf95dfc4'), u'b': 4}
{u'a': 6, u'_id': ObjectId('57ea7b568365d9a2cf95dfc5'), u'b': 7}

Delete

特定のデータを削除したい場合は、remove()を使う。条件は引数で指定する。

>>> result = co.remove({'a': 1})
>>> for d in co.find():
...     print d
...
{u'a': 100, u'c': 5, u'_id': ObjectId('57ea7b568365d9a2cf95dfc4'), u'b': 4}
{u'a': 6, u'_id': ObjectId('57ea7b568365d9a2cf95dfc5'), u'b': 7}

collectionごと消し去りたい場合は、drop()を使う。

>>> result = co.drop()
>>> for d in co.find():
...     print d
...
>>>

参考文献

Homebrewがアップデートできない時の対処法

しばらくHomebrewを使っていなくて、mongodbを使うために久々にコマンドを打ったらエラーが出た。

$ brew update
/usr/local/bin/brew: /usr/local/Library/brew.rb: /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby: bad interpreter: No such file or directory
/usr/local/bin/brew: line 26: /usr/local/Library/brew.rb: Undefined error: 0

OSをバージョンアップさせると、このような現象が起こるらしい。 これからまたSierraにバージョンアップする予定があるのだが。。 まあ、また同様のエラーが起きた時のためにも、手順をまとめておく。

エラー対処法

このエラー自体はHomebrewのissueになっている のだが、既にクローズしており以下の操作が必要。

# cd /usr/local/Library
# git pull origin master

ディレクトリーを/usr/local/Library以外に変更した場合は、上記の操作でエラーが出る。 僕は上記で成功したので未検証だが、その場合は以下の操作が必要。

# git fetch --all
# git reset --hard origin/master

確認

早速さっき失敗したupdateを実行。問題なく終了。

# brew update
remote: Counting objects: 934, done.
...

インストール済みのformulaを確認。 mongodbは以前CentOSで使っていたと思ったら、Macでも使っていた。。

# brew list
... mongodb ...

バージョンを確認したら、だいぶ古い。

# brew outdated
...
mongodb (2.2.2-x86_64) < 3.2.9
...

いい機会なので、更新のあるformulaをすべてupgrade。 結構時間がかかるのでターゲットのformulaだけでいい場合は、それをupgradeの次に記述。

# brew upgrade
...
==> Installing mongodb
==> Downloading https://homebrew.bintray.com/bottles/mongodb-3.2.9.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring mongodb-3.2.9.el_capitan.bottle.tar.gz
==> Caveats
To have launchd start mongodb now and restart at login:
  brew services start mongodb
Or, if you don't want/need a background service you can just run:
  mongod --config /usr/local/etc/mongod.conf
...

更新のあるformulaを確認して、すべて更新されたか確認。

# brew outdated
#

古いformulaが残ったままなので削除。

# brew cleanup -n
...
Would remove: /usr/local/Cellar/mongodb/2.2.2-x86_64 (20 files, 170M)
...
#

その他

実は、やたらエラーが出まくってたのだが、 El Capitanから/usr/local以下が書き換えられなくなったと聞いた気がするけど、それが原因かも。

Error: Running Homebrew as root is extremely dangerous. As Homebrew does not
drop privileges on installation you are giving all build scripts full access
to your system. As a result of the macOS sandbox not handling the root user
correctly HOMEBREW_NO_SANDBOX has been set so the sandbox will not be used. If
we have not merged a pull request to add privilege dropping by November 1st
2016 running Homebrew as root will be disabled. No Homebrew maintainers plan
to work on this functionality.

参考文献

python-firebaseでCRUD操作

Python経由でFirebaseのDBを操作することができるので、CRUD操作の方法をまとめた。

インストール

pipでrequestsとpython-firebaseをインストール。 python-firebase 1.2のチュートリアルだと、requestsのバージョン指定がある。 でも僕の場合、既にインストール済みver2.4.3を使ってるけど問題ないから関係ないっぽい。

$ sudo pip install requests==1.1.0
$ sudo pip install python-firebase

接続

インストールが完了したら、早速Firebaseに接続。2行でOK。

>>> from firebase import firebase
>>> firebase = firebase.FirebaseApplication("https://<your-app-id>.firebaseio.com", None)

Create

putを使う。渡すのはdictのlist。引数は順に、url、key、value。urlは不要。 valueは単純に1とかの値でもいいし、dictのlistみたいな入り組んだのでもOK。とにかくjsonライクなデータ。jsonでもいい。 ちなみにdictのlistってなんて呼んでるんでしょうか、皆さん。

>>> data = [{'id': 'A001', 'name': 'Google'}, {'id': 'A002', 'name': 'Microsoft'}, {'id': 'A003', 'name': 'IBM'}]
>>> result = firebase.put('', '/test', data)

Read

putで入れたデータはgetで取得。keyで指定したtest以下を読み込む。

>>> result = firebase.get('/test', None)
>>> print result
[{u'id': u'A001', u'name': u'Google'}, {u'id': u'A002', u'name': u'Microsoft'}, {u'id': u'A003', u'name': u'IBM'}]

Update

これもputでOK。dictのlistを渡したときの最初のidをA001からB001に変えてみる。 最初なので、/test/0となる。

>>> firebase.put('', '/test/0/id', 'B001')
u'B001'
>>> result = firebase.get('/test', None)
>>> print result
[{u'id': u'B001', u'name': u'Google'}, {u'id': u'A002', u'name': u'Microsoft'}, {u'id': u'A003', u'name': u'IBM'}]

Delete

そのままのメソッド名のdeleteを使う。test以下をまるごと消してみる。

>>> result = firebase.delete('/test', None)
>>> result = firebase.get('/test', None)
>>> print result
None

その他

postを使ってもデータの挿入可能。チュートリアルだと、これが使われているけど、 IDが割り振られるので、不要な人はputでいいと思う。

>>> result = firebase.post('/test', data)
>>> result = firebase.get('/test', None)
>>> print result
{u'-KRxkKQIBasry9UCf7Bc': [{u'id': u'A001', u'name': u'Google'}, {u'id': u'A002', u'name': u'Microsoft'}, {u'id': u'A003', u'name': u'IBM'}]}

参考文献

FirebaseのApiKeyとAppIDはHTMLソースにコピペしてもセキュア

FirebaseのWebアプリ作成チュートリアルでは、ApiKeyやAppIDなどの情報をhtmlソースにコピペすることなっている。 これらの情報が公開されることに少し抵抗があったので、焼け石に水だが、これらの情報は別のjavascriptファイルにして、 htmlから呼び出す仕様にしてみたが、リンクをクリックすれば分かるし、はやりセキュアなのか気になったので調査したみた。

index.html

...
    <script src="https://www.gstatic.com/firebasejs/3.3.2/firebase.js"></script>
    <script src="app.js"></script>
...

app.js

...
var config = {
  apiKey: "<your-api-key>",
  authDomain: "<your-app-id>.firebaseapp.com",
  databaseURL: "https://<your-app-id>.firebaseio.com",
  storageBucket: "<your-app-id>.appspot.com",
};
...

結論

他のユーザーがApiKeyやAppIDを知っていても、credentials(認証情報)を知らない限り、 セキュリティ上の問題はないらしい。バレちゃいけない情報の確認方法は以下の通り。

  1. Visit https://console.developers.google.com/apis
  2. Go to your firebase project
  3. Go to credentials

参考文献

Firebase入門に最適な記事とリアルタイムデータベース体験

Firebaseとは?から簡単なWebアプリをホスティングサーバーにデプロイするまでは、 Firebaseの始め方が分りやすかった。 入門はこれだけ読めばOKだと思う。

リアルタイムデータベース

自分でも同様のアプリを作って、Firebaseの最も大きな特徴でリアルタイムデータベースという 誰かがデータを更新すると自動で他の端末にも反映される機能を体験してみた。

一番手前がChromeで、その奥がSafariで、一番奥がFirebaseのリアルタイムデータベースになる。 Chromeの入力内容が、各々で即座に反映されているのが分かる。

f:id:Shoto:20160917213237g:plain

htmlコードは次の通り。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Welcome to Firebase Hosting</title>

    <script src="https://www.gstatic.com/firebasejs/3.3.2/firebase.js"></script>
    <script src="app.js"></script>

  </head>
  <body>
    <div id="message">
      <h4>Input and Enter</h1>
      <p id="outputLabel"></p>
      <input type="text" id="inputText" onkeypress="return enterKeyAction(event);"></li>
    </div>

    <script>
      var db = firebase.database();
      var testText = db.ref("/sample/io");

      function enterKeyAction(e)
      {
        if(e.keyCode == 13){
          var text = document.getElementById("inputText").value;
          testText.set({text:text});
        }
      }

      testText.on("value", function(snapshot) {
        document.getElementById("outputLabel").innerText = snapshot.val().text;
      });
    </script>
  </body>
</html>

Api KeyとDB URLなどは別ファイルにして、念のためhtmlから呼び出す感じにした。

// Initialize Firebase
var config = {
  apiKey: "<your-api-key>",
  authDomain: "<your-app-id>.firebaseapp.com",
  databaseURL: "https://<your-app-id>.firebaseio.com",
  storageBucket: "<your-app-id>.appspot.com",
};
firebase.initializeApp(config);

参考文献

Macでnpmを使う

Firebaseを始めようとしたら、npmコマンドが見当たらない、と言われ出鼻をくじかれた。

$ npm install -g firebase-tools
-bash: npm: command not found

調べてみたら、Node.jsの管理ツールとのこと。 Pythonでいうところのpipみたいなものか、と理解して、Installing node.js on OSX 10.11 El Capitman を参考にして、npm利用環境の設定とテストを行った。

設定

https://nodejs.org から.dmgをダウンロードして実行するだけ。 2016年9月現在、「v4.5.0 LTS」と「v6.5.0 Current」があるが、どちらでもよい。ぼくはv4.5.0を選んだ。

f:id:Shoto:20160911202949p:plain

テスト

パスに /usr/local/bin が入っていることを確認。

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

インストールしたバージョンと一致していることを確認。

$ node -v
v4.5.0

javascriptが実行でき、再びターミナルに戻れればOK。

$ node
> console.log('hello node')
hello node
undefined
>
(To exit, press ^C again or type .exit)
>
$

参考文献

ネット切断頻度が高くなってきたので、ルーターのファームウェアをアップデートした

Netflixを見ていると、たまに字幕が現れなくなることがあった。原因は、ルーターの不具合でネットが切断されていたためで、これは一度ルーターの電源を落として再起動させることで解決できていた。しかし、最近は1日数回と頻度が高くなり、とても快適なインターネットライフが楽しめる状況ではなくなってきたので、ファームウェアのアップデートしてネットが切断する不具合を修正した。

アップデート手順

ぼくは、BUFFALOのWZR-600DHPという2012年に発売されたルーターを使っているのだが、それについての手順は以下の通り。

  1. ファームウェアをダウンロードして解凍
  2. ブラウザから192.168.11.1に接続
  3. テキストボックスに、ユーザー名:admin、パスワード:passwordと入力
  4. [ファームウェアを更新する]をクリック
  5. [ファイルを選択]をクリック
  6. ダウンロードしておいたファームウェアを指定して開く
  7. [設定]ボタンをクリック

ルーターが赤く点滅し始めるので、5分ほど待って点滅しなくなったら、ルーターを再起動させて、ネットに繋がることが確認できれば終わり。ルーターとPCを有線LANでつないでアップデートするように、との記述もあったが不要だった。

ネットが切断される他の原因

ネットが切断される原因は全部で8つほどあるので、今回のファームウェアをアップデートしてもダメだった場合は、以下を試してみる予定。

  • 原因1: ファームウェアが最新版ではない
  • 原因2: 電波の干渉を受け不安定になっている
  • 原因3: 無線子機のドライバーが正しく動作していない
  • 原因4: IPアドレスの自動割当てが正常に機能していない
  • 原因5: 無線接続ツールが重複してインストールされている
  • 原因6: セキュリティーソフトなどが影響している
  • 原因7: 暗号化キーの更新の際に無線が途切れる
  • 原因8: 無線親機と端末の電波が弱い