MongoDBで外部ファイル化したJavaScriptを実行する際に、引数を渡して実行したいことが
多かったのですが、色々調べても正式なやり方が見つからなかったので、工夫して実現してみました。
その他にも、個人的に便利な実行方法をまとめて記載してみます。
方針
外部JavaScriptに引数を直接渡せないようなので、仕方ないので適当なシェルを作り、
シェルに渡された引数を出力し、外部JavaScriptへ渡すことにします。
シェルからJSへの引数の渡し方
まずは
mongo --quiet << EOS
var result = load("/xxx/mapreduce.js")
EOS
などとすると、外部JSを実行できるので、その前に
var arg1 = "$1"
のように記載して、シェルの引数を出力してJSに渡します。
mongo --quiet << EOS
var arg1 = "$1"
var result = load("/xxx/mapreduce.js")
EOS
$1の部分が、シェルに渡された引数の出力になります。
実行する際は、
sh /xxx/mapreduce_with_args.sh hoge
などとすると、arg1の値が"hoge"となり、外部JS内で使えるようになります。
ついでにJavaScriptをutil化してMapReduce内で使う
ついでですが、JavaScriptの内容をUtil化し、再利用したい場合も多いです。
普通のやり方ではMapReduce内にUtil関数を渡せないので、
一度
var util = new function(){
this.hogeFunc = function(xxx){・・・}
}
などとしてUtil関数をまとめた後、
db.system.js.save({"_id": "util", "value": util});
として system.js に保存しておきます。
参考にさせていただいたページ:
http://muddydixon.hatenablog.com/entry/20110325/1301076643
実行例まとめ
エラーチェックなどを付け足しつつまとめると、例えば以下のようなやり方になります。
sh /xxx/mapreduce_with_args.sh hogeDb hugaName
mongo --quiet << EOS
try{
// シェルの引数を出力してJavaScriptに渡す
var dbName = "$1"
if(!dbName){
// 引数チェック
throw new Error("Validation Error")
}
// 対象のdbを引数にしたがって変更
var db = new Mongo().getDB(dbName);
// その他のパラメータ(対象dbの変更後に設定しないとダメみたい)
var targetName = "$2"
// utilの内容を読み込み、保存
var result1 = load("/xxx/util.js");
// mapreduce実行
var result2 = load("/xxx/mapreduce.js")
}catch(e){
print(e.stack);
}
EOS
// util定義
var util = new function(){
this.hogeFunc = function(xxx){
return yyy;
}
}
// utilの内容を system.js に保存
db.system.js.save({"_id": "util", "value": util});
// 引数の内容を使ってクエリを組み立てるなど
var query = {name : targetName}
var map = function() {
// utilの内容を使って処理を行う
var yyy = util.hogeFunc(xxx);
...
}
mapreduce実行