シェルスクリプトを使用してmongoコマンドを実行する方法


404

mongoシェルスクリプト、たとえばスクリプトでコマンドを実行したいtest.sh

#!/bin/sh
mongo myDbName
db.mycollection.findOne()
show collections

このスクリプトをを介して実行する./test.shと、MongoDBへの接続は確立されますが、次のコマンドは実行されません。

シェルスクリプトを使用して他のコマンドを実行する方法test.sh

回答:


452

コマンド--evalが単一のコマンドの場合は、フラグを使用してコマンドを評価することもできます。

mongo --eval "printjson(db.serverStatus())"

注: $記号で始まるMongo演算子を使用している場合、シェルが演算子を環境変数として評価しないように、eval引数を一重引用符で囲みます。

mongo --eval 'db.mycollection.update({"name":"foo"},{$set:{"this":"that"}});' myDbName

そうでない場合、次のようなものが表示されることがあります。

mongo --eval "db.test.update({\"name\":\"foo\"},{$set:{\"this\":\"that\"}});"
> E QUERY    SyntaxError: Unexpected token :

35
以下のため.find()の操作は、次のような文書、印刷する結果オブジェクトに対して操作を呼び出すために必要toArray()かをshellPrint()。例mongo userdb --eval "printjson(db.users.find().toArray())"
Gingi 2014年

4
mongo <ip>:<port> / db --eval "printjson(db.serverStatus())"またはmongo <ip>:<port> / db <mongoCommands.jsのような接続文字列を指定して、それを防ぐ必要がありました。常に「テスト」に接続
dev

9
ありがとう@Gingi-私の優先する方法はmongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()"... simples :)
Matt Fletcher

4
「type for it for more」を表示するのではなく、すべての結果を取得したい
Randy L

6
@Amida mongo --eval "db.version()" --quietたとえば、言うすべてのノイズを出力しないようにすることができます
Fermin Silva

327

mongoスクリプトを.jsファイルに入れます。

次に実行します mongo < yourFile.js

例:

demo.js //ファイルにスクリプトがあります

use sample  //db name
show collections

このファイルを「c:\ db-scripts」に保存します

次に、cmdプロンプトで「c:\ db-scripts」に移動します

C:\db-scripts>mongo < demo.js

これはmongoでコードを実行し、出力を表示します

C:\db-scripts>mongo < demo.js
Mongo shell version: 3.0.4
Connecting to: test
switched to db sample
users   //collection name
tasks   //collection name
bye
C:\db-scripts>

13
まさに文字通り.. mongoシェルに入力するのとまったく同じコマンドを受け取り、それらのコマンドを.jsファイルに保存して、パラメーターとしてコマンドに渡しますmongo
Matt

7
--evalステートメント(提供されている場合)でmongoインタープリターに設定したものは、スクリプト(提供されている場合)が実行されたときにスコープ内に残ることに注意してください。これを使用して、スクリプトをより再利用可能にすることができます。mongo --eval "somevar = 'someval';" db_name script_that_uses_somevar.js
Andrew J

9
@Matt -シェルが提供する非JavaScriptのコマンドが実行されるJavaScriptファイルでは使用できないので、ことを注意use dbNameしてshow dbs、シェルの内部プロンプトではなく、内側からから動作します.jsファイル。JavaScript以外のコマンドには同等のJavaScriptがあるため、これは制限ではなく、注意が必要なことです。
Tad Marshall

4
データベースの名前、ユーザー名、パスワードを指定する必要がある場合は、次のようにすることができますmongo dbName -u userName -p "password with spaces" scriptToRun.js
KevinL

1
mongoプロンプトを開いたままにする方法はありますか?別名モンゴに「さようなら」と言わせたくない。
アレクサンダーミルズ


64

これを次のファイルに入れますtest.js

db.mycollection.findOne()
db.getCollectionNames().forEach(function(collection) {
  print(collection);
});

次に、それをで実行しmongo myDbName test.jsます。


2
bashからスクリプトに値を渡す方法は?変数としてbashで使用可能なdbに名前を挿入し、それをscript(js)に渡したい
Sasikanth

これははるかに優れた解決策です。mongoにファイルをパイプインすると、js構文エラーが発生します。
Storm Muller

41

これに関する公式のドキュメントページもあります。

そのページの例は次のとおりです。

mongo server:27017/dbname --quiet my_commands.js
mongo test --eval "printjson(db.getCollectionNames())"

32

以下のシェルスクリプトもうまく機能しました...確かに、Antoninが最初に述べたリダイレクトを使用する必要がありました...これにより、hereドキュメントをテストするというアイデアが生まれました。

function testMongoScript {
    mongo <<EOF
    use mydb
    db.leads.findOne()
    db.leads.find().count()
EOF
}

13
正解です。複数のコマンドの場合、これはまた動作します:echo -e "use mydb\ndb.leads.findOne()\ndb.leads.find().count()" | mongo
デニスMünkle

JSファイル内で「use mydb」を使用できないため、間違いなく便利です。
buzypi 2013年

これありがとう!ようやく電話できますuse another_db。:-)
IonicăBizău

1
実際には、モンゴスクリプト内からDBを切り替えることができますdb = db.getSiblingDB('otherdb');
joeytwiddle

ちょうど私が必要としたもの。しかし、あなたが唯一の1つのデータベースを使用する必要がある場合、あなたは例えば、モンゴコマンドにデータベース名を渡すことができますmongo mydb <<EOFなど
spikyjt


20

私は、David Youngが言及している「ヒアドキュメント」構文を使用しています。しかし、落とし穴があります。

#!/usr/bin/sh

mongo <db> <<EOF
db.<collection>.find({
  fieldName: { $exists: true }
})
.forEach( printjson );
EOF

上記は機能しません。「$ exists」というフレーズはシェルによって認識され、「exists」という名前の環境変数の値で置き換えられるためです。おそらく存在しないので、シェルを展開すると、次のようになります。

#!/usr/bin/sh

mongo <db> <<EOF
db.<collection>.find({
  fieldName: { : true }
})
.forEach( printjson );
EOF

それを通過させるには、2つのオプションがあります。1つは醜いです、1つはかなりいいです。まず、醜いもの:$記号をエスケープします。

#!/usr/bin/sh

mongo <db> <<EOF
db.<collection>.find({
  fieldName: { \$exists: true }
})
.forEach( printjson );
EOF

逃げるのを忘れやすいので、これはお勧めしません。

もう1つのオプションは、次のようにEOFをエスケープすることです。

#!/usr/bin/sh

mongo <db> <<\EOF
db.<collection>.find({
  fieldName: { $exists: true }
})
.forEach( printjson );
EOF

これで、必要なすべてのドル記号をヒアドキュメントに入れることができ、ドル記号は無視されます。欠点:mongoスクリプトにシェルパラメータ/変数を配置する必要がある場合、これは機能しません。

あなたが遊ぶことができる別のオプションは、あなたのシバンを台無しにすることです。例えば、

#!/bin/env mongo
<some mongo stuff>

このソリューションにはいくつかの問題があります。

  1. コマンドラインからmongoシェルスクリプトを実行可能にしようとしている場合にのみ機能します。通常のシェルコマンドとmongoシェルコマンドを混在させることはできません。そうすることで保存するのは、コマンドラインで「mongo」と入力する必要がないだけです...(もちろん十分な理由があります)

  2. 「mongo <some-js-file>」とまったく同じように機能します。つまり、「use <db>」コマンドを使用できません。

私はデータベース名をシバンに追加しようとしましたが、あなたはうまくいくと思います。残念ながら、システムがシバン行を処理する方法、最初のスペースの後のすべてが単一のパラメーターとして(引用符で囲まれているように)envコマンドに渡され、envはそれを見つけて実行できません。

代わりに、データベースの変更を次のようにスクリプト自体に埋め込む必要があります。

#!/bin/env mongo
db = db.getSiblingDB('<db>');
<your script>

人生のすべてのことと同じように、「それを行うには複数の方法があります!」


18

認証を有効にしている場合:

mongo -u username -p password --authenticationDatabase auth_db_name < your_script.js

16

スクリプトファイルを作成します。書き込みコマンド:

#!/bin/sh
mongo < file.js

ではfile.js、書き込みあなたのmongoクエリ:

db.collection.find({"myValue":null}).count();


12

で提案されているようにtheTuxRacerevalコマンドを使用できます。以前のようにそれが見つからない場合は、デフォルトのdbで操作を実行しない場合は、db名に追加することもできます。

mongo <dbname> --eval "printjson(db.something.find())"

7

よろしくお願いしますprintf!Linux環境では、ショーを1つのファイルだけで実行するためのより良い方法があります。mongoCmds.js複数のコマンドを含む2つのファイルがあるとします。

use someDb
db.someColl.find()

そしてドライバーシェルファイル、 runMongoCmds.sh

mongo < mongoCmds.js

代わりに、runMongoCmds.shを含むファイルを1つだけ

printf "use someDb\ndb.someColl.find()" | mongo

Bashはよりprintfも堅牢でecho\nコマンド間で複数行に強制することができます。



6

私の場合、\n実行したい次のmongoコマンドのセパレータとして便利に使用でき、それらをパイプしますmongo

echo $'use your_db\ndb.yourCollection.find()' | mongo

4

--shellフラグはJavaScriptファイルにも使用できます

 mongo --shell /path/to/jsfile/test.js 

私はこれがjsの実行後にシェルを開いたままにすると思いますか? mongo /path/to/jsfile/test.jsjsも削除します。
UpTheCreek


3

最近mongodbからPostgresに移行しました。これが私がスクリプトを使用した方法です。

mongo < scripts.js > inserts.sql

を読み、scripts.jsに出力リダイレクトしinserts.sqlます。

scripts.js こんな感じ

use myDb;
var string = "INSERT INTO table(a, b) VALUES";
db.getCollection('collectionName').find({}).forEach(function (object) {
    string += "('" + String(object.description) + "','" + object.name + "'),";
});
print(string.substring(0, string.length - 1), ";");

inserts.sql こんな感じ

INSERT INTO table(a, b) VALUES('abc', 'Alice'), ('def', 'Bob'), ('ghi', 'Claire');

1
非常に興味深いが、元の質問に関してトピックから外れています。
jlyonsmith

How to execute mongo commands through shell scripts?これはトピック外ではありません。実は、タイトルのせいでこの質問に行きました。ですから、私のような人々はそのような答えを読むことで利益を得ます。また、おもちゃの例ではなく、非常に便利な方法を示しています。
mythicalcoder

2

1行で処理する場合は、簡単な方法です。

file.sh --> db.EXPECTED_COLLECTION.remove("_id":1234)

cat file.sh | mongo <EXPECTED_COLLECTION>

1

より大きなBashスクリプト内からMongo Shellスクリプトを実行するためのさまざまなオプションを書きまし


1

mongo引数(--quiet、dbnameなど)を渡す機能を持つ単一シェルスクリプトソリューション:

#!/usr/bin/env -S mongo --quiet localhost:27017/test

cur = db.myCollection.find({});
while(cur.hasNext()) {
  printjson(cur.next());
}

この-Sフラグはすべてのプラットフォームで機能するわけではありません。


0

レプリカセットを使用する場合、書き込みはPRIMARYで行う必要があるため、通常は次のような構文を使用して、どのホストがマスターであるかを把握する必要がないようにします。

mongo -host myReplicaset/anyKnownReplica

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.