カテゴリー : MongoDB

[MongoDB] データベースファイルが保存されるパス dbpath を確認する

MongoDB のデータベースファイルが保存される dbpath は db.serverCmdLineOpts() の実行結果から確認できます。

MongoDB

dbpath を確認するクエリ

db.serverCmdLineOpts().parsed.dbpath           // MongoDB 2.4 and older
db.serverCmdLineOpts().parsed.storage.dbPath   // MongoDB 2.6+

(例) db.serverCmdLineOpts() の実行結果

dbPath 以外にも config ファイルや systemLog ファイルの出力先なども確認できます。

> db.serverCmdLineOpts()
{
	"argv" : [
		"/usr/local/opt/mongodb/bin/mongod",
		"--config",
		"/usr/local/etc/mongod.conf"
	],
	"parsed" : {
		"config" : "/usr/local/etc/mongod.conf",
		"net" : {
			"bindIp" : "127.0.0.1"
		},
		"storage" : {
			"dbPath" : "/usr/local/var/mongodb"
		},
		"systemLog" : {
			"destination" : "file",
			"logAppend" : true,
			"path" : "/usr/local/var/log/mongodb/mongo.log"
		}
	},
	"ok" : 1
}

以上です。

参考情報

[MongoDB] db.runCommand( { cloneCollection } ) の使い方

MongoDB で collection をコピーする db.runCommand( { cloneCollection } ) の使い方をご紹介します。

MongoDB

host: targethost1, port: 27017 と host: currenthost, port: 27018 で mongod instance が2つ立ち上がっている状態とします。

以下のようなクエリで targethost1:27017 の targetDb database にある users collection から verified_at が null ではない document を currentDb に同じ collection 名でコピーできます。

mongo --host currenthost --port 27018 currentDb
 
var query = { verified_at : { $ne : null } };
db.runCommand( { cloneCollection: 'targetDb.users', from: 'targethost1:27017', query : query } );

コピーした collection 名を変更したい場合は renameCollection でできます。

以上です。

[MongoDB] Array の length で sort するために aggregate を使う

MongoDB で Array type な field を length で sort して取得するサンプルクエリをご紹介します。

MongoDB

MongoDB Query

db.posts.aggregate(
[
  { $unwind: "$likes" },
  { $group: {
      _id: "$_id",
      size: { $sum: 1 }
    }
  },
  { $sort: { size: -1 } }
])

Results

{ "_id" : ObjectId("514e23e06aeaa880410321aa"), "size" : 590 }
{ "_id" : ObjectId("545c796972b4c28015ab4eac"), "size" : 395 }
{ "_id" : ObjectId("51440f7d4ca4c41367001dff"), "size" : 321 }
{ "_id" : ObjectId("51d6eef05204c9046100031d"), "size" : 315 }
{ "_id" : ObjectId("54ae81f1f158d13d60c50116"), "size" : 271 }
//...

参考情報

[MongoDB] 銀行口座のスキーマ定義

以前、Mongoose (MongoDB) で銀行口座の情報を取り扱う Scheme の定義をしたときに悩んで付けた field 名を公開します。

MongoDB

BANK_ACCOUNT_TYPE =
  SAVINGS: 1
  CURRENT: 2
 
BANK_ACCOUNT_TYPE_KEYS = Object.keys(BANK_ACCOUNT_TYPE)
BANK_ACCOUNT_TYPE_PATTERN = BANK_ACCOUNT_TYPE_KEYS.map (k)-> BANK_ACCOUNT_TYPE[k]
 
HogeScheme = new Scheme
bank_account:
  bank_name:
    type: String
  bank_code:
    type: String
  branch_name:
    type: String
  branch_code:
    type: String
  account_type:
    type: Number
    enum: BANK_ACCOUNT_TYPE_PATTERN
  account_number:
    type: Number
  account_holder_name:
    type: String
  account_holder_name_kana:
    type: String

というような感じにしました。

[MongoDB] field を削除するコマンド

MongoDB で不要なフィールドを削除するには db.collection.update を $unset で利用します。

MongoDB

$unset のためのデータ事前準備

まず、検証用のデータを insert します。今回は3件新規登録します。

> db.users.insert( { name : 'test' , age : 20 } )
> db.users.insert( { name : 'hoge' , age : 50 } )
> db.users.insert( { name : 'spam' , age : 90 } )
 
> db.users.find()
{ "_id" : ObjectId("55102489395c0a2d41edd220"), "name" : "test", "age" : 20 }
{ "_id" : ObjectId("551024c0395c0a2d41edd221"), "name" : "hoge", "age" : 50 }
{ "_id" : ObjectId("551025fc395c0a2d41edd222"), "name" : "spam", "age" : 90 }

1件だけ $unset する

特定の _id の document の field を削除する場合、第一引数に条件を指定して、1件だけしか削除しないように第四引数に false を指定します。

> db.users.update( { _id : ObjectId( "55102489395c0a2d41edd220" ) } , { $unset : { age : 1 } } , false , false )
> db.users.find()
{ "_id" : ObjectId("55102489395c0a2d41edd220"), "name" : "test" }
{ "_id" : ObjectId("551024c0395c0a2d41edd221"), "name" : "hoge", "age" : 50 }
{ "_id" : ObjectId("551025fc395c0a2d41edd222"), "name" : "spam", "age" : 90 }

全件 $unset する

全ての document の特定の field を削除する場合、第一引数に {} を指定して全ドキュメントを対象にして、第四引数に true を指定して該当する全ドキュメントのフィールドを削除対象にします。

> db.users.update( { } , { $unset : { age : 1 } } , false , true )
> db.users.find()
{ "_id" : ObjectId("55102489395c0a2d41edd220"), "name" : "test" }
{ "_id" : ObjectId("551024c0395c0a2d41edd221"), "name" : "hoge" }
{ "_id" : ObjectId("551025fc395c0a2d41edd222"), "name" : "spam" }

$unset の使い方まとめ

最後に注意点として、update メソッドはすべてのドキュメントの field を吹っ飛ばす可能性があるので、本番データではできるだけ使わないようにしたいですね。

参考情報

[MongoDB] Failed global initialization: BadValue Invalid or no user locale set. Please ensure LANG and/or LC_* environment variables are set correctly.

mongo shell に入ろうとするとエラーが発生しました。

$ mongo myDb
Failed global initialization: BadValue Invalid or no user locale set. Please ensure LANG and/or LC_* environment variables are set correctly.

MongoDB

取り急ぎ、デフォルトのロケールを使用するようにすれば mongo shell に接続できるようになります。

$ export LC_ALL=C

あとは、下記の記事によると不要な mongo のパッケージをアンインストールすると解決するらしいです。

[MongoDB] CentOS6.4でmongo 2.6.5 を使ったらエラーが出過ぎたので、2.6.4に変更した際のメモ – Qiita

参考情報

[MongoDB] mongo shell から別 DB へ接続してクエリを実行する

MongoDB で別データベースに接続してクエリを実行する方法をご紹介します。

MongoDB

前提

2つの DB サーバで保存する collection を分けて管理しているとします。

データベース1

  • Host: mongodb1
  • Port: 27017
  • DB: myDb

データベース2

  • Host: mongodb2
  • Port: 27017
  • DB: myDb

別 DB への connection を作成する方法

mongo shell で query を実行するときに別 DB の collection も扱いたい場合、その DB への connection を作成してあげればいいです。

$ mongo mongodb1/myDb
mongodb1> db2 = connect("mongodb2:27017/myDb")
connecting to: mongodb2:27017/myDb
myDb
 
// mongodb2 サーバにの mdDb に保存されている somecollections のデータを扱うことができる
mongodb1> db2.somecollections.findOne()

DB サーバが1台のときは気にしなくてよかったのですが、複数台になると別 DB サーバへのコネクションを扱う Tips も知っておけば今までどおり mongo shell からクエリを実行しまくれますね。

参考情報

[MongoDB] aggregate の実行時間を確認する方法

mongo shell で db.collection.aggregate() の実行時間を確認するコマンドをご紹介します。

MongoDB

time mongo dbname –eval ‘query’ で実行時間を確認する

bash や zsh などから time コマンドを使って mongo –eval でクエリを渡して、実行時間を確認しました。

$ time mongo dbname --eval 'db.orders.aggregate([ { $match: { customer_id: "abcdefg", payment_system: "paypal" } } , { $group: { _id: "$user" } } ])'
MongoDB shell version: 2.6.5
connecting to: dbname
[object Object]
 
real	0m0.120s
user	0m0.044s
sys	0m0.004s

aggregate の explain オプションではダメなのか?

db.collection.aggregate(pipeline, options) の第二引数に explain を Boolean で指定できます。

しかし、これは db.collection.find().explain() の実行結果とは少し違うみたいで、実行時間については確認できませんでした。

  db.users.aggregate( [ ], { explain: true } )
{
	"stages" : [
		{
			"$cursor" : {
				"query" : {
 
				},
				"plan" : {
					"cursor" : "BasicCursor",
					"isMultiKey" : false,
					"scanAndOrder" : false,
					"allPlans" : [
						{
							"cursor" : "BasicCursor",
							"isMultiKey" : false,
							"scanAndOrder" : false
						}
					]
				}
			}
		}
	],
	"ok" : 1
}

time コマンドを使う以外のやり方をご存知でしたら教えて下さい。

参考情報

[MongoDB] mongo shell での表示件数は DBQuery.shellBatchSize で設定できる

mongo shell での表示件数はデフォルト 20 件なのですが、これを変更するには DBQuery.shellBatchSize の値を変更すればいいみたいです。

MongoDB

// 表示件数を 500 件にしたい場合
DBQuery.shellBatchSize = 500;

クエリの結果が何件とか予め分かっている場合、その件数を設定すれば一度に結果を全件出力できるので it を入力しなくてよくて便利だったりします。

db.users.find()
...
Type "it" for more
 
// 普段だったら 20 件ごとに it を入力しないといけない

以上です。

参考情報

MongoDB の GUI クライアント

MongoDB を mongo shell からでなく GUI クライアントから操作できた方が楽なこともあると聞いて、アプリ入れてみました。

MongoDB

とりあえず、開発環境で使うために Robomongo をインストールしてみました。

Robomongo — shell-centric MongoDB management tool (MongoDB Admin UI)

しばらく、使ってみたいと思います。