ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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


S
Sahil Gulati

如果命令只是一个命令,您还可以使用 --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 :

对于 .find() 操作,您需要在结果对象上调用操作以打印文档,例如 toArray()shellPrint()。例如,mongo userdb --eval "printjson(db.users.find().toArray())"
我必须指定连接字符串,如 mongo :/db --eval "printjson(db.serverStatus())" 或 mongo :/db < mongoCommands.js 以防止它总是连接到“测试”
谢谢@Gingi - 我的首选方法是 mongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()" ... simples :)
我希望我能得到所有的结果,而不是看到它打印出来“输入'it' for more”
@Amida 你可以做 mongo --eval "db.version()" --quiet 例如避免打印你说的所有噪音
P
Prasanth Jaya

将您的 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>

从字面上看.. 您采用与输入到 mongo shell 完全相同的命令,将这些命令保存到 .js 文件,并将其作为参数传递给 mongo 命令。
值得注意的是,在执行脚本(如果提供)时,您在 --eval 语句(如果提供)中为 mongo 解释器设置的任何内容都将保留在范围内。您可以使用它使您的脚本更可重用,例如。 mongo --eval "somevar='someval';" db_name script_that_uses_somevar.js
@Matt -- 请注意,shell 提供的非 JavaScript 命令在执行的 JavaScript 文件中不可用,因此 use dbNameshow dbs 将在 shell 的内部提示符下工作,但不能在 .js 文件内工作。非 JavaScript 命令有 JavaScript 等价物,所以这不是限制,只是您需要注意的事情。
如果需要指定数据库名、用户名、密码,可以做mongo dbName -u userName -p "password with spaces" scriptToRun.js
使用 mongo --quiet 不打印再见和版本。
i
indianMonk

这适用于我在 Linux 下:

mongo < script.js

对于较新版本的 mongodb

mongosh < script.js

T
Theo

将其放入名为 test.js 的文件中:

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

然后使用 mongo myDbName test.js 运行它。


如何将值从 bash 传递给脚本?我想将名称插入到 db 中,该名称在 bash 中作为变量可用,并且我想将其传递给脚本(js)
这是一个更好的解决方案,当我将文件通过管道传输到 mongo 时,会出现 js 语法错误。
在循环内部,不执行其他命令。
A
Apurv

还有一个关于此的 official documentation 页面。

该页面的示例包括:

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

D
David H. Young

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

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

很好的答案!对于多个命令,这也适用:echo -e "use mydb\ndb.leads.findOne()\ndb.leads.find().count()" | mongo
绝对有用,因为您不能在 JS 文件中使用“使用 mydb”。
这次真是万分感谢!最后我可以调用 use another_db。 :-)
实际上,您可以从 mongo 脚本中切换 DB:db = db.getSiblingDB('otherdb');
正是我需要的。但是,如果您只需要使用一个数据库,您可以将数据库名称传递给 mongo 命令,例如 mongo mydb <<EOF 等。
i
indianMonk

如果您启用了身份验证:

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

对于较新的版本

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

J
John Arrowwood

我使用 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>

这个解决方案有几个问题:

仅当您尝试从命令行使 mongo shell 脚本可执行时,它才有效。您不能将常规 shell 命令与 mongo shell 命令混合使用。而且您这样做所节省的只是不必在命令行上键入“mongo”......(当然,这是有道理的)它的功能与“mongo ”完全相同,这意味着它不会让你使用“使用”命令。

我已经尝试将数据库名称添加到 shebang,您认为这会起作用。不幸的是,系统处理 shebang 行的方式,第一个空格之后的所有内容都作为单个参数(就像引用一样)传递给 env 命令,并且 env 无法找到并运行它。

相反,您必须将数据库更改嵌入脚本本身,如下所示:

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

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


如果您引用您的 HEREDOC 定界符,shell 将不会解释或替换任何内容,例如代替 blah blah << HEREDOC_EOF 的东西 EOF 使用 blah blah << "EOF" stuf EOF
这是一个很好的答案!如何将 shell 变量传递给查询?
答案是不要逃避你的HEREDOC。然后,您将能够在其中进行替换。抓住的是,你将不得不逃避任何文字美元符号。
i
indianMonk

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

mongo --host="the.server.ip:port" databaseName theScript.js 

对于较新版本的 mongodb

mongosh --host="the.server.ip:port" databaseName theScript.js 


i
indianMonk

创建脚本文件;写命令:

#!/bin/sh
mongo < file.js

对于较新的版本 mongosh < file.js

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

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

M
Mark Butler

这个怎么样:

echo "db.mycollection.findOne()" | mongo myDbName
echo "show collections" | mongo myDbName

或者更具可读性: echo "db.mycollection.findOne()" | mongo myDbName --quiet | python -m json.tool
这对于在加载 .mongorc (docs.mongodb.org/manual/reference/program/mongo/…) 后执行某些操作很有用
我可以将结果放入 shell 中的变量中吗?
i
indianMonk

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

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

较新版本的 mongodb

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

i
indianMonk

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

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

较新版本的 mongodb

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

i
indianMonk

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

use someDb
db.someColl.find()

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

mongo < mongoCmds.js

较新版本的 mongodb

mongosh < mongoCmds.js

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

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

Bash 的 printfecho 健壮得多,并且允许命令之间的 \n 强制它们在多行上。


E
Erdem ÖZDEMİR
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF

J
Jackson Harry

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

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

我认为这只是在 js 执行后打开外壳? mongo /path/to/jsfile/test.js 也会执行 js。
T
Talespin_Kit
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"

m
mythicalcoder

最近从 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');

非常有趣,但与原始问题无关。
How to execute mongo commands through shell scripts? 这不是题外话。事实上,由于标题,我提出了这个问题。所以像我这样的人会受益于阅读这样的答案。另外,我在示例中给出了一个非常有用的方法,而不是一个玩具示例。
E
Erçin Akçay

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

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

cat file.sh | mongo <EXPECTED_COLLECTION>

y
yǝsʞǝla

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

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

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

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


对我来说这似乎很奇怪,这并没有得到更广泛的赞赏......您也可以只是将完整的路径指向特定的 mongo,对吧?
R
RSX

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

mongo -host myReplicaset/anyKnownReplica


这并没有回答“如何通过 shell 脚本执行 mongo 命令?”这个问题。