如何通过Shell脚本执行mongo命令?


403

我想mongo在外壳脚本中执行命令,例如在脚本中执行命令test.sh

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

当我通过执行脚本时./test.sh,将建立与MongoDB的连接,但不会执行以下命令。

如何通过Shell脚本执行其他命令test.sh

Answers:


452

--eval如果只是单个命令,您还可以使用标志来评估命令。

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

请注意:如果您使用的是Mongo运算符(以$符号开头),则需要将eval参数用单引号引起来,以防止Shell将运算符作为环境变量进行评估:

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来防止始终连接到“测试”
开发人员

9
感谢@Gingi-我的首选方法是mongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()"...简单:)
Matt Fletcher

4
我希望我能得到所有结果,而不是看到它引出“输入'it'来表示更多信息”
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 shell的命令完全相同,将这些命令保存到.js文件中,并将其作为参数传递给该mongo命令。
马特

7
值得注意的是,您在--eval语句(如果提供)中设置给mongo解释器的任何内容在执行脚本(如果提供)时将保留在范围内。您可以使用它来使脚本更可重用,例如。mongo --eval“ somevar ='someval';” db_name script_that_uses_somevar.js
Andrew J

9
@马特-请注意,非JavaScript命令,外壳提供不是一个执行JavaScript文件可用,因此use dbNameshow dbs从内部迅速而从壳里面的不工作.js文件。非JavaScript命令具有等效的JavaScript,因此这不是限制,只是您需要注意的事项。
塔德·马歇尔

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将值传递到脚本?我想将名称插入db中,该名称可以在bash中作为变量使用,我想将其传递给script(js)
Sasikanth 2015年

这是一个更好的解决方案,当我将文件传输到mongo时,出现js语法错误。
Storm Muller

41

也有关于此的官方文档页面。

该页面上的示例包括:

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

32

下面的shell脚本对我也很好用...肯定必须使用Antonin最初提到的重定向...这给了我测试此处文档的想法。

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
DennisMünkle2013年

绝对有用,因为您不能在JS文件中使用“ use mydb”。
buzypi

这次真是万分感谢!最后我可以打电话了use another_db。:-)
尼卡比曹

1
实际上,您可以从mongo脚本中切换数据库:db = db.getSiblingDB('otherdb');
joeytwiddle

正是我所需要的。不过,如果你只需要使用一个数据库,你可以通过该数据库名蒙戈命令,如mongo mydb <<EOF
spikyjt


19

我使用David Young提到的“ heredoc”语法。但是有一个问题:

#!/usr/bin/sh

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

上面的命令不起作用,因为shell会看到短语“ $ exists”,并用名为“ exists”的环境变量的值代替。可能不存在,因此在shell扩展后,它变为:

#!/usr/bin/sh

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

为了使它通过,您有两个选择。一个很丑,一个很不错。一,丑陋的一面:逃脱$符号:

#!/usr/bin/sh

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

我不建议这样做,因为很容易忘记逃脱。

另一个选择是逃避EOF,如下所示:

#!/usr/bin/sh

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

现在,您可以将所有所需的美元符号放入heredoc中,而美元符号将被忽略。不利的一面:如果您需要在mongo脚本中放入shell参数/变量,那将不起作用。

您可以使用的另一种选择是弄乱您的shebang。例如,

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

此解决方案存在几个问题:

  1. 仅当您尝试从命令行使mongo shell脚本可执行时,它才有效。您不能将常规的shell命令与mongo shell命令混合使用。这样,您节省的所有事情都不必在命令行上键入“ mongo” ...(当然,这足够合理)

  2. 它的功能与“ mongo <some-js-file>”完全相同,这意味着它不允许您使用“ use <db>”命令。

我尝试过将数据库名称添加到shebang中,您认为这会起作用。不幸的是,系统处理shebang行的方式是,第一个空格之后的所有内容都作为单个参数(如被引用)传递给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

如的建议theTuxRacer,您可以使用eval命令,对于那些像我一样遗失它的人,如果您不尝试对默认数据库执行操作,还可以添加数据库名称。

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

7

谢谢你printf!在Linux环境中,这是只运行一个文件的更好方法。假设您有两个文件,mongoCmds.js其中包含多个命令:

use someDb
db.someColl.find()

然后是驱动程序外壳文件, runMongoCmds.sh

mongo < mongoCmds.js

相反,只有一个文件,其中包含runMongoCmds.sh

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

Bash printf比Bash 健壮得多,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.js也会执行js。
UpTheCreek

4
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"

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 '18

How to execute mongo commands through shell scripts?这不是题外话。实际上,由于标题,我遇到了这个问题。所以像我这样的人受益于阅读这样的答案。另外,我在示例中提供了一个非常有用的方法,而不是玩具示例。
mythicalcoder



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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.