456

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

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

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

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

4

21 回答 21

527

--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 :
于 2011-05-14T07:12:33.417 回答
363

将您的 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>
于 2011-01-29T15:28:11.173 回答
107

这适用于我在 Linux 下:

mongo < script.js
于 2011-07-31T18:05:04.693 回答
67

把它放在一个名为的文件中test.js

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

然后运行它mongo myDbName test.js

于 2011-01-29T18:36:47.630 回答
45

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

该页面的示例包括:

mongo server:27017/dbname --quiet my_commands.js
mongo test --eval "printjson(db.getCollectionNames())"
于 2012-04-18T02:14:12.440 回答
36

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

function testMongoScript {
    mongo <<EOF
    use mydb
    db.leads.findOne()
    db.leads.find().count()
EOF
}
于 2011-08-21T04:44:34.420 回答
25

如果您启用了身份验证:

mongo -u username -p password --authenticationDatabase auth_db_name < your_script.js
于 2017-06-02T00:11:06.843 回答
24

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

#!/usr/bin/sh

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

以上将不起作用,因为短语“$exists”将被 shell 看到并替换为名为“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 中,而美元符号将被忽略。不利的一面:如果您需要将 shell 参数/变量放在 mongo 脚本中,这将不起作用。

您可以玩的另一个选择是弄乱您的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>

就像生活中的任何事情一样,“有不止一种方法可以做到!”

于 2014-08-29T14:19:08.547 回答
23

在我的设置中,我必须使用:

mongo --host="the.server.ip:port" databaseName theScript.js 
于 2012-02-03T19:42:35.103 回答
17

创建脚本文件;写命令:

#!/bin/sh
mongo < file.js

file.js编写您的 mongo 查询时:

db.collection.find({"myValue":null}).count();
于 2017-08-21T12:42:21.157 回答
16

这个怎么样:

echo "db.mycollection.findOne()" | mongo myDbName
echo "show collections" | mongo myDbName
于 2014-09-08T17:40:29.300 回答
12

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

mongo <dbname> --eval "printjson(db.something.find())"
于 2015-12-22T20:07:43.747 回答
11

谢谢printf!在 Linux 环境中,这里有一种更好的方法,可以只让一个文件运行该节目。假设您有两个文件,mongoCmds.js其中包含多个命令:

use someDb
db.someColl.find()

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

mongo < mongoCmds.js

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

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

Bashprintf比它更健壮,echo并且允许\n在命令之间强制它们在多行上。

于 2015-12-17T21:27:57.387 回答
11

在我的情况下,我可以方便地\n用作我想要执行的下一个 mongo 命令的分隔符,然后将它们通过管道传输到mongo

echo $'use your_db\ndb.yourCollection.find()' | mongo
于 2018-08-29T09:57:43.820 回答
8
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF
于 2018-04-27T07:38:00.880 回答
4

--shell 标志也可用于 javascript 文件

 mongo --shell /path/to/jsfile/test.js 
于 2015-04-30T12:57:41.873 回答
4
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"
于 2016-12-06T15:30:29.300 回答
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');
于 2017-05-07T07:30:24.710 回答
3

如果你想用一条线处理它,这是一种简单的方法。

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

cat file.sh | mongo <EXPECTED_COLLECTION>
于 2018-01-22T15:50:07.590 回答
1

能够传递 mongo 参数(--quiet、dbname 等)的单 shell 脚本解决方案:

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

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

-S标志可能不适用于所有平台。

于 2019-07-30T02:47:52.733 回答
1

使用副本集时,必须在 PRIMARY 上进行写入,因此我通常使用这样的语法,以避免必须确定哪个主机是主服务器:

mongo -host myReplicaset/anyKnownReplica

于 2019-11-05T12:15:15.677 回答