Symfoware

Symfowareについての考察blog

PHPからMongoDB 2.0.6 に接続する(PHP MongoDB Driver)

PHPからMongoDBに接続してみます。

Webサーバーの構築はこちらの手順。
Debian 7 + nginx + php-fpmな環境を構築する

MongoDBのインストールはこちらの手順で構築した環境を使用します。
Debian 7にMongoDB 2.0.6 をapt-getでインストールする




接続ドライバーのインストール



PHP MongoDB Driverを使用することにしました。
PHP MongoDB Driver

必要なモジュールをapt-getでインストールします。


# apt-get install php5-dev php5-cli php-pear g++ make




peclコマンドでドライバーをインストール。
認証を使用しない場合は、Build with Cyrus SASLはnoで良いと思います。


# pecl install mongo
downloading mongo-1.5.4.tgz ...
Starting to download mongo-1.5.4.tgz (191,364 bytes)
.........................................done: 191,364 bytes
116 source files, building
running: phpize
Configuring for:
PHP Api Version:         20100412
Zend Module Api No:     20100525
Zend Extension Api No: 220100525
Build with Cyrus SASL (MongoDB Enterprise Authentication) support? [no] :

(略)

Build process completed successfully
Installing '/usr/lib/php5/20100525/mongo.so'
install ok: channel://pecl.php.net/mongo-1.5.4
configuration option "php_ini" is not set to php.ini location
You should add "extension=mongo.so" to php.ini




mongo.soが生成されました。
設定ファイルを作成し、ライブラリがロードされるようにします。


# vi /etc/php5/fpm/conf.d/mongo.ini




mongo.iniに記載する内容は以下のとおり。


; configuration for php mongo module
extension=mongo.so




php-fpmを使用していますので、一旦再起動。


# /etc/init.d/php5-fpm restart




phpinfoを表示して、mongoの項目が表示されれば
ライブラリのロードは成功しています。

432_01.png





接続のサンプル



プログラムは、こちらのドキュメントを参考に作成しました。
http://jp1.php.net/manual/ja/mongo.tutorial.php
http://jp1.php.net/mongo



  1. <?php
  2. // MongoDBに接続
  3. $client = new MongoClient();
  4. // データベース選択(どちらでもok)
  5. //$db = $client->selectDB('php_db');
  6. $db = $client->php_db;
  7. // コレクション取得(どちらでもok)
  8. //$col = $db->selectCollection('php_collection');
  9. $col = $db->php_collection;
  10. // データの登録
  11. $doc = array('title' => 'タイトル', 'value' => 'テスト登録');
  12. $col->insert($doc);
  13. // コレクション全件検索
  14. $cursor = $col->find();
  15. foreach($cursor as $doc) {
  16.     echo $doc['title'] . ':' . $doc['value'] . '<br/>';
  17. }




そっけないですが、登録と検索が行えることが確認できました。

432_02.png






検索条件の指定



findで検索条件を指定してみます。
3件ほどデータを登録しました。


  1. <?php
  2. // MongoDBに接続
  3. $client = new MongoClient();
  4. // データベース選択(どちらでもok)
  5. //$db = $client->selectDB('php_db');
  6. $db = $client->php_db;
  7. // 一旦コレクションを削除
  8. $db->dropCollection('php_collection');
  9. // コレクション取得(どちらでもok)
  10. //$col = $db->selectCollection('php_collection');
  11. $col = $db->php_collection;
  12. // データの登録
  13. $doc = array('number' => 1, 'title' => '一番目', 'value' => '一番目の値');
  14. $col->insert($doc);
  15. $doc = array('number' => 2, 'title' => '二番目', 'value' => '二番目の値');
  16. $col->insert($doc);
  17. $doc = array('number' => 3, 'title' => '三番目', 'value' => '三番目の値');
  18. $col->insert($doc);
  19. // コレクション全件検索
  20. $cursor = $col->find();
  21. foreach($cursor as $doc) {
  22.     echo $doc['title'] . ':' . $doc['value'] . '<br/>';
  23. }




432_03.png



number:2のデータだけ表示してみます。


  1. <?php
  2. // MongoDBに接続
  3. $client = new MongoClient();
  4. // データベース選択(どちらでもok)
  5. //$db = $client->selectDB('php_db');
  6. $db = $client->php_db;
  7. // コレクション取得(どちらでもok)
  8. //$col = $db->selectCollection('php_collection');
  9. $col = $db->php_collection;
  10. // number:2のデータを検索
  11. $cursor = $col->find(array('number' => 2));
  12. foreach($cursor as $doc) {
  13.     echo $doc['title'] . ':' . $doc['value'] . '<br/>';
  14. }




いい感じです。

432_04.png




ソート



nuber:3からデータを降順で取得してみます。


  1. <?php
  2. // MongoDBに接続
  3. $client = new MongoClient();
  4. // データベース選択(どちらでもok)
  5. //$db = $client->selectDB('php_db');
  6. $db = $client->php_db;
  7. // コレクション取得(どちらでもok)
  8. //$col = $db->selectCollection('php_collection');
  9. $col = $db->php_collection;
  10. // numberでソート
  11. $cursor = $col->find()->sort(array('number' => -1));
  12. foreach($cursor as $doc) {
  13.     echo $doc['title'] . ':' . $doc['value'] . '<br/>';
  14. }




432_05.png

引数に「1」を指定すると昇順、「-1」を指定すると降順になります。
http://jp1.php.net/manual/ja/mongocursor.sort.php



テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/27(日) 20:11:26|
  2. MongoDB
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

MongoDB PyMongo 2.7.1 findでandやor、$gt,$ltを使用する

MongoDBで検索するとき、andやorで条件が指定できるか調べてみました。
サンプルはPyMongo 2.7.1を使用したプログラムです。


テストデータ



こんなテストデータを用意します。


'user':'symfo', 'values':{'key1':'v1'}, 'tags' : ['dog', 'cat'], 'number' : 1
'user':'mongo', 'values':{'key1':'v2'}, 'tags' : ['cat'], 'number' : 2
'user':'mongo', 'values':{'key1':'v3'}, 'tags' : ['mouse', 'cat', 'dog'], 'number' : 3
'user':'riak', 'values':{'key1':'v4'}, 'tags' : [], 'number' : 4




登録に使用したプログラムは以下のとおり。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. col.insert({'user':'symfo', 'values':{'key1':'v1'}, 'tags' : ['dog', 'cat'], 'number' : 1})
  9. col.insert({'user':'mongo', 'values':{'key1':'v2'}, 'tags' : ['cat'], 'number' : 2})
  10. col.insert({'user':'mongo', 'values':{'key1':'v3'}, 'tags' : ['mouse', 'cat', 'dog'], 'number' : 3})
  11. col.insert({'user':'riak', 'values':{'key1':'v4'}, 'tags' : [], 'number' : 4})







and条件指定



tagsに「dog」と「cat」を持つドキュメントを検索します。
http://docs.mongodb.org/manual/reference/operator/query/and/

findに「$and」を指定すれば良いようです。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # tagsに「dog」と「cat」があるドキュメントを検索
  9. ret = col.find({ '$and' : [{'tags': 'dog'}, {'tags': 'cat'}]})
  10. for doc in ret:
  11.     print(doc)





想定通りの結果が得られました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab309f'), u'values': {u'key1': u'v1'}, u'number': 1, u'tags': [u'dog', u'cat'], u'user': u'symfo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}








or条件指定



tagsに「dog」または「cat」を持つドキュメントを検索します。
http://docs.mongodb.org/manual/reference/operator/query/or/

findに「$or」を指定すれば良いようです。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # tagsに「dog」または「cat」があるドキュメントを検索
  9. ret = col.find({ '$or' : [{'tags': 'dog'}, {'tags': 'cat'}]})
  10. for doc in ret:
  11.     print(doc)





3つのドキュメントが抽出出来ました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab309f'), u'values': {u'key1': u'v1'}, u'number': 1, u'tags': [u'dog', u'cat'], u'user': u'symfo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}







指定値より大きい値



numberが2より大きい値を検索してみます。
条件に「$gt」を指定すればOK。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # numberが2より大きいドキュメント
  9. ret = col.find({ 'number' : {'$gt' : 2}})
  10. for doc in ret:
  11.     print(doc)




numberが「3」と「4」のドキュメントが取得出来ました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a2'), u'values': {u'key1': u'v4'}, u'number': 4, u'tags': [], u'user': u'riak'}







指定値を含み大きい値



numberが2以上のドキュメントを検索してみます。
条件に「$gte」を指定してやります。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # numberが2以上のドキュメント
  9. ret = col.find({ 'number' : {'$gte' : 2}})
  10. for doc in ret:
  11.     print(doc)





numberが2,3,4のドキュメントが取得出来ました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a2'), u'values': {u'key1': u'v4'}, u'number': 4, u'tags': [], u'user': u'riak'}







指定値より小さい値



numberが3未満のドキュメントを検索します。
条件に「$lt」を指定。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # numberが3未満のドキュメント
  9. ret = col.find({ 'number' : {'$lt' : 3}})
  10. for doc in ret:
  11.     print(doc)





numberが「1」と「2」のドキュメントが取得出来ました。


f0a24079ab30a2'), u'values': {u'key1': u'v4'}, u'number': 4, u'tags': [], u'user': u'riak'}
baranche@atropos:~/dev/python$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab309f'), u'values': {u'key1': u'v1'}, u'number': 1, u'tags': [u'dog', u'cat'], u'user': u'symfo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}







指定値以下の値



numberが3以下のドキュメントを検索します。
条件に「$lte」を指定。



  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # numberが3以下のドキュメント
  9. ret = col.find({ 'number' : {'$lte' : 3}})
  10. for doc in ret:
  11.     print(doc)





numberが1,2,3のドキュメントが取得出来ました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab309f'), u'values': {u'key1': u'v1'}, u'number': 1, u'tags': [u'dog', u'cat'], u'user': u'symfo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}







範囲指定



numberが2以上、3以下のドキュメントを検索します。
条件を並べて記載してやればOK。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # numberが2以上3以下のドキュメント
  9. ret = col.find({ 'number' : {'$gte' :2, '$lte' : 3}})
  10. for doc in ret:
  11.     print(doc)





狙い通り、numberが「2」と「3」のドキュメントが取得出来ました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}







辞書型の値を検索



ドキュメントのvaluesには、辞書型のデータを保存しています。
「key1」のvalueが「v2」の値を検索してみます。

フィールドの指定を「values.key1」としてやれば検索できます。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # valuesのkey1が「v2」のデータ
  9. ret = col.find({ 'values.key1' : 'v2'})
  10. for doc in ret:
  11.     print(doc)





ちゃんと1件取得出来ました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}







ソート



せっかくなので、ソートも見てみます。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # numberでソート
  9. ret = col.find().sort('number')
  10. for doc in ret:
  11.     print(doc)




number順にソートされます。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab309f'), u'values': {u'key1': u'v1'}, u'number': 1, u'tags': [u'dog', u'cat'], u'user': u'symfo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a2'), u'values': {u'key1': u'v4'}, u'number': 4, u'tags': [], u'user': u'riak'}





逆順にするには、pymongo.DESCENDINGを指定します。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # numberでソート
  9. ret = col.find().sort('number', pymongo.DESCENDING)
  10. for doc in ret:
  11.     print(doc)





逆順になりました。


$ python sample.py
{u'_id': ObjectId('53d4c25804f0a24079ab30a2'), u'values': {u'key1': u'v4'}, u'number': 4, u'tags': [], u'user': u'riak'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a1'), u'values': {u'key1': u'v3'}, u'number': 3, u'tags': [u'mouse', u'cat', u'dog'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab30a0'), u'values': {u'key1': u'v2'}, u'number': 2, u'tags': [u'cat'], u'user': u'mongo'}
{u'_id': ObjectId('53d4c25804f0a24079ab309f'), u'values': {u'key1': u'v1'}, u'number': 1, u'tags': [u'dog', u'cat'], u'user': u'symfo'}




複合ソートなども実行可能です。
詳細はこちらのドキュメントのsortの項目参照。
cursor – Tools for iterating over MongoDB query results

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/27(日) 18:41:49|
  2. MongoDB
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

MongoDB PyMongo 2.7.1でMap,Reduceのサンプル

MongoDBのようなドキュメントのデータベースといえば、
Map,Reduceの機能がウリのはず。

PyMongoでPythonからMap,Reduceの機能を使用してみます。


サンプルデータ



こちらのドキュメントを参考にしました。
Aggregation Examples

こんなデータを事前に登録しておきます。


'user':'symfo', 'value':'symfo first data', 'tags' : ['dog', 'cat']
'user':'mongo', 'value':'mongo first data', 'tags' : ['cat']
'user':'mongo', 'value':'mongo second data', 'tags' : ['mouse', 'cat', 'dog']
'user':'riak', 'value':'riak first data', 'tags' : []




登録に使用したプログラムはこんな感じ。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. col.insert({'user':'symfo', 'value':'symfo first data', 'tags' : ['dog', 'cat']})
  9. col.insert({'user':'mongo', 'value':'mongo first data', 'tags' : ['cat']})
  10. col.insert({'user':'mongo', 'value':'mongo second data', 'tags' : ['mouse', 'cat', 'dog']})
  11. col.insert({'user':'riak', 'value':'riak first data', 'tags' : []})







タグに使用されている名称を集計



タグに使用されている文字と、そのタグが使用されている件数を集計してみます。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. import bson.code
  4. # MongoDBに接続
  5. client = pymongo.MongoClient('192.168.1.110', 27017)
  6. db = client.mongo_test
  7. # test_collectionを取得
  8. col = db.test_collection
  9. # タグを分割するJavaScript
  10. mapper = bson.code.Code("""
  11. function () {
  12.     this.tags.forEach(function(z) {
  13.         emit(z, 1);
  14.     });
  15. }
  16. """)
  17. # タグを集計するJavaScript
  18. reducer = bson.code.Code("""
  19. function (key, values) {
  20.     var total = 0;
  21.     for (var i = 0; i < values.length; i++) {
  22.         total += values[i];
  23.     }
  24.     return total;
  25. }
  26. """)
  27. result = col.map_reduce(mapper, reducer, "myresults")
  28. for doc in result.find():
  29.     print(doc)




myresultsというコレクションが作成され、そこに集計結果が登録されます。
実行すると、各タグの名称と使用回数が表示されました。


$ python sample.py
{u'_id': u'cat', u'value': 3.0}
{u'_id': u'dog', u'value': 2.0}
{u'_id': u'mouse', u'value': 1.0}






集計する条件を指定



userがmongoのタグの使用状況を集計してみます。
map_reduceを実行するとき、queryを指定すればOK。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. import bson.code
  4. # MongoDBに接続
  5. client = pymongo.MongoClient('192.168.1.110', 27017)
  6. db = client.mongo_test
  7. # test_collectionを取得
  8. col = db.test_collection
  9. # タグを分割するJavaScript
  10. mapper = bson.code.Code("""
  11. function () {
  12.     this.tags.forEach(function(z) {
  13.         emit(z, 1);
  14.     });
  15. }
  16. """)
  17. # タグを集計するJavaScript
  18. reducer = bson.code.Code("""
  19. function (key, values) {
  20.     var total = 0;
  21.     for (var i = 0; i < values.length; i++) {
  22.         total += values[i];
  23.     }
  24.     return total;
  25. }
  26. """)
  27. # user:mongoのデータのみ集計
  28. result = col.map_reduce(mapper, reducer, "myresults", query={"user": 'mongo'})
  29. for doc in result.find():
  30.     print(doc)





user:mongoのデータのみ集計できました。


$ python sample.py
{u'_id': u'cat', u'value': 2.0}
{u'_id': u'dog', u'value': 1.0}
{u'_id': u'mouse', u'value': 1.0}







Group



user毎に、各々何件ドキュメントが存在するかgroupを使用して数えてみます。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. import bson.code
  4. # MongoDBに接続
  5. client = pymongo.MongoClient('192.168.1.110', 27017)
  6. db = client.mongo_test
  7. # test_collectionを取得
  8. col = db.test_collection
  9. # ユーザーごとの投稿数集計
  10. reducer = bson.code.Code("""
  11. function(obj, prev){
  12.     prev.count++;
  13. }
  14. """)
  15. results = col.group(key={"user":1}, condition={}, initial={"count": 0}, reduce=reducer)
  16. for doc in results:
  17.     print(doc)




SQLでいうgroup byですね。


$ python sample.py
{u'count': 1.0, u'user': u'symfo'}
{u'count': 2.0, u'user': u'mongo'}
{u'count': 1.0, u'user': u'riak'}

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/27(日) 17:49:42|
  2. MongoDB
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

MongoDB PyMongo 2.7.1で「_id」を自分で指定して、登録や検索を行う

MongoDBにPythonからPyMongoを使用して操作してみています。
PyMongo 2.7.1のインストールと使い方(チュートリアル)
MongoDB PyMongo 2.7.1 よく使う機能のまとめ

データベースの仕様上、「_id」というフィールドが自動的に付与され、
ユニークなObjectIdが設定されます。

これを自分で指定できないものか。
例えば、日付をyyyy-MM-dd形式にして_idとして使用したいとか。


ObjectIdに日付を指定



まず試してみたのは、ObjectIdを自分で作成して見る方法。
※これはうまく行きません。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. import bson.objectid
  4. # MongoDBに接続
  5. client = pymongo.MongoClient('192.168.1.110', 27017)
  6. db = client.mongo_test
  7. # test_collectionを取得
  8. col = db.test_collection
  9. # ObjectIdを自分で生成して登録
  10. _id = bson.objectid.ObjectId('2014-05-06')
  11. col.insert({'_id':_id, 'value':'test'})




実行すると、「bson.errors.InvalidId: 2014-05-06 is not a valid ObjectId」という
エラーが発生します。


$ python sample.py
Traceback (most recent call last):
File "sample.py", line 13, in <module>
    _id = bson.objectid.ObjectId('2014-05-06')
File "build/bdist.linux-x86_64/egg/bson/objectid.py", line 92, in __init__
File "build/bdist.linux-x86_64/egg/bson/objectid.py", line 196, in __validate
bson.errors.InvalidId: 2014-05-06 is not a valid ObjectId





どうすれば良いのか悩んだのですが、オチは簡単。
_idに文字列をそのまま指定すればOKです。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # ObjectIdを自分で生成して登録
  9. _id = '2014-05-06'
  10. col.insert({'_id':_id, 'value':'test'})
  11. for doc in col.find({'_id':_id}):
  12.     print(doc)





実行すると、ちゃんと登録できたことがわかりました。


$ python sample.py
{u'_id': u'2014-05-06', u'value': u'test'}




注意点は、もう一度このプログラムを実行するとキー重複のエラーになります。


$ python sample.py
Traceback (most recent call last):
File "sample.py", line 13, in <module>
    col.insert({'_id':_id, 'value':'test'})
File "build/bdist.linux-x86_64/egg/pymongo/collection.py", line 412, in insert
File "build/bdist.linux-x86_64/egg/pymongo/mongo_client.py", line 1121, in _send_message
File "build/bdist.linux-x86_64/egg/pymongo/mongo_client.py", line 1062, in __check_response_to_last_error
pymongo.errors.DuplicateKeyError: E11000 duplicate key error index: mongo_test.test_collection.$_id_ dup key: { : "2014-05-06" }




事前にremoveしておくか、saveを使用するようにします。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # ObjectIdを自分で生成して登録
  9. _id = '2014-05-06'
  10. col.save({'_id':_id, 'value':'test'})
  11. for doc in col.find({'_id':_id}):
  12.     print(doc)




saveは_idに存在しない値を指定した場合は、insertと同じ動きになるようです。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/27(日) 16:04:23|
  2. MongoDB
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

MongoDB PyMongo 2.7.1 よく使う機能のまとめ

MongoDBへPythonからPyMongoを使用して接続。
PyMongoのチュートリアルを試してみました。

PyMongo 2.7.1のインストールと使い方(チュートリアル)


チュートリアルに登場していない、よく使うことになりそうな機能を試してみます。


MongoClient



MongoDBに接続するためのオブジェクトです。
ドキュメントはこちら。
mongo_client – Tools for connecting to MongoDB

database_names()で、データベースの一覧表示。
drop_database(name_or_database)で、データベースの削除が行えます。


「mongo_test」というデータベースを作成して、名前を表示。
その後、データベースを削除するサンプルはこんな感じになりました。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. # データベース「mongo_test」を作成
  6. db = client.mongo_test
  7. # 適当にデータを挿入
  8. db.test_collection.insert({'test':'test'})
  9. # データベースの一覧を表示
  10. for database_name in client.database_names():
  11.     print(database_name)
  12. print('-'*10)
  13. # データベースを削除
  14. client.drop_database(db)
  15. # こちらでもok
  16. #client.drop_database('mongo_test')
  17. # 再度、データベース名を表示
  18. for database_name in client.database_names():
  19.     print(database_name)





実行後、「mongo_test」データベースが削除されたことが確認できます。


$ python sample.py
mongo_test
test_database
local
----------
test_database
local







データベース関連



データベースにあるコレクションの情報を取得してみます。
ドキュメントはこちら。
database – Database level operations


「mongo_test」データベースに「col_1」と「col_2」という2つのコレクションを作成。
コレクション名の一覧を表示したあと、「col_1」を削除してみます。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. # データベース「mongo_test」を作成
  6. db = client.mongo_test
  7. # col_1にデータを登録
  8. db.col_1.insert({'test':'test'})
  9. # col_2にデータを登録
  10. db.col_2.insert({'test':'test'})
  11. # コレクションの一覧を表示
  12. for collection_name in db.collection_names():
  13.     print(collection_name)
  14. print('-'*10)
  15. # col_1を削除
  16. db.drop_collection(db.col_1)
  17. # こちらでもok
  18. #db.drop_collection('col_1')
  19. # 再度、コレクションの一覧を表示
  20. for collection_name in db.collection_names():
  21.     print(collection_name)




system.indexesコレクションは自動的に作成されるコレクションです。
想定通り、col_1が削除出来ました。


$ python sample.py
system.indexes
col_2
col_1
----------
system.indexes
col_2







コレクション内のドキュメント操作



コレクションに登録されているドキュメントを操作してみます。
collection – Collection level operations


データの登録は「insert」を使用します。
サンプルはこんな感じ。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # 「insert」でデータを登録
  9. col.insert({'number':1, 'value':u'number-1 data'})
  10. # findでデータを取得
  11. for doc in col.find():
  12.     print(doc)




自動的に「_id」フィールドが作成されます。


$ python sample.py
{u'_id': ObjectId('53d4985504f0a21fcf773263'), u'number': 1, u'value': u'number-1 data'}






このデータを更新したい場合は、「save」を使用します。
サンプルはこんな感じ。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # find_oneで number:1のデータを取得
  9. doc = col.find_one({'number':1})
  10. # valueの内容を変更
  11. doc['value'] = 'nuber-1 data changed'
  12. # saveで保存
  13. col.save(doc)
  14. # findでデータを取得。内容を表示
  15. for doc in col.find():
  16.     print(doc)




ちゃんと値が変更されました。


$ python sample.py
{u'_id': ObjectId('53d4985504f0a21fcf773263'), u'number': 1, u'value': u'nuber-1 data changed'}





データを削除するには「remove」を使用します。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. print( col.find_one({'number':1}) )
  9. # removeで number:1のデータを削除
  10. col.remove({'number':1})
  11. print('-'*10)
  12. print( col.find_one({'number':1}) )




削除後、データが取得できないことが確認できました。


$ python sample.py
{u'_id': ObjectId('53d4985504f0a21fcf773263'), u'number': 1, u'value': u'nuber-1 data changed'}
----------
None






条件を指定してデータを更新したい場合は、「update」を使用します。
サンプルはこんな感じ。


  1. # -*- coding:utf-8 -*-
  2. import pymongo
  3. # MongoDBに接続
  4. client = pymongo.MongoClient('192.168.1.110', 27017)
  5. db = client.mongo_test
  6. # test_collectionを取得
  7. col = db.test_collection
  8. # 適当にテストデータを登録
  9. col.insert({'number':1, 'value':'number-1 value'})
  10. col.insert({'number':2, 'value':'number-2 value'})
  11. col.insert({'number':3, 'value':'number-3 value'})
  12. # 内容を表示
  13. for doc in col.find():
  14.     print(doc)
  15. # updateでnumber:2のデータを更新
  16. col.update({'number':2}, {'$set': {'value': 'number-2 value changed'}})
  17. print('-'*10)
  18. for doc in col.find():
  19.     print(doc)




狙った値だけ変更できました。


$ python sample.py
{u'_id': ObjectId('53d49daa04f0a223e2ea9cb5'), u'number': 1, u'value': u'number-1 value'}
{u'_id': ObjectId('53d49daa04f0a223e2ea9cb6'), u'number': 2, u'value': u'number-2 value'}
{u'_id': ObjectId('53d49daa04f0a223e2ea9cb7'), u'number': 3, u'value': u'number-3 value'}
----------
{u'_id': ObjectId('53d49daa04f0a223e2ea9cb5'), u'number': 1, u'value': u'number-1 value'}
{u'_id': ObjectId('53d49daa04f0a223e2ea9cb6'), u'number': 2, u'value': u'number-2 value changed'}
{u'_id': ObjectId('53d49daa04f0a223e2ea9cb7'), u'number': 3, u'value': u'number-3 value'}


テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/27(日) 15:39:30|
  2. MongoDB
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ