Как выполнять команды монго через скрипты оболочки?

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 :
theTuxRacer
источник
35
Для .find()операций необходимо вызвать операцию для объекта результата для печати документов, например toArray()или shellPrint(). например,mongo userdb --eval "printjson(db.users.find().toArray())"
Gingi
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()"... простейший :)
Мэтт Флетчер
4
Я хотел бы получить ВСЕ результаты, вместо того, чтобы видеть это как "напиши" для большего "
Рэнди Л
6
@ Амида, ты можешь сделать, mongo --eval "db.version()" --quietнапример, чтобы не печатать весь шум, который ты говоришь
Фермин Сильва
327

Поместите ваш скрипт монго в .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

Это выполнит код в монго и покажет результат

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>
Matt
источник
13
В буквальном смысле ... вы берете те же самые команды, которые вы вводите в оболочку mongo, сохраняете эти команды в .jsфайл и передаете их как параметр в mongoкоманду.
Мэтт
7
Стоит отметить, что все, что вы задали в операторе --eval (если он указан) для интерпретатора mongo, останется в области действия при выполнении вашего скрипта (если он есть). Вы можете использовать это, чтобы сделать ваши сценарии более пригодными для повторного использования, например. mongo --eval "somevar = 'someval';" db_name script_that_uses_somevar.js
Эндрю Дж
9
@ Matt - Обратите внимание , что команды без JavaScript , что оболочка обеспечивает не доступны в исполняемый файл JavaScript, так use dbNameи show dbsбудет работать с внутренней подсказки , но не изнутри оболочечному .jsфайла. Для команд, не относящихся к JavaScript, есть эквиваленты JavaScript, так что это не ограничение, а просто то, о чем вам нужно знать.
Тэд Маршалл
4
Если вам нужно указать имя базы данных, имя пользователя, пароль, вы можете это сделатьmongo dbName -u userName -p "password with spaces" scriptToRun.js
KevinL
1
Есть ли способ сохранить приглашение Монго открытым? АКА Я не хочу, чтобы Монго сказал мне "пока".
Александр Миллс
102

Это работает для меня под Linux:

mongo < script.js
Антонин Бретцнайдр
источник
64

Поместите это в файл с именем test.js:

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

затем запустите его с mongo myDbName test.js.

Тео
источник
2
Как передать значения в скрипт из bash? Я хочу вставить имя в db, которое доступно в bash как переменную, и я хочу передать его в скрипт (js)
Sasikanth
Это гораздо лучшее решение: когда я передаю в файл монго, я получаю ошибки синтаксиса js.
Шторм Мюллер
41

Об этом также есть официальная страница документации .

Примеры с этой страницы включают в себя:

mongo server:27017/dbname --quiet my_commands.js
mongo test --eval "printjson(db.getCollectionNames())"
thaddeusmt
источник
32

Сценарий оболочки ниже также работал хорошо для меня ... определенно пришлось использовать редирект, который Антонин упомянул сначала ... который дал мне идею протестировать здесь документ.

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
Деннис Мюнкле
Определенно полезно, потому что вы не можете использовать «использовать mydb» в файле JS.
buzypi
Спасибо тебе за это! Наконец я могу позвонить use another_db. :-)
Ионика Бизэ
1
На самом деле вы можете переключать БД из монго-скрипта:db = db.getSiblingDB('otherdb');
joeytwiddle
Как раз то, что мне было нужно. Однако, если вам нужно использовать только одну базу данных, вы можете передать имя базы данных команде mongo, например, mongo mydb <<EOFи т. Д.
spikyjt
22

В моей настройке я должен использовать:

mongo --host="the.server.ip:port" databaseName theScript.js 
Эд Уильямс
источник
20

Я использую синтаксис «heredoc», который упоминает Дэвид Янг. Но тут есть одна загвоздка

#!/usr/bin/sh

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

Вышеприведенное НЕ будет работать, потому что фраза «$ Существует» будет видна оболочкой и заменена значением переменной среды с именем «существует». Которого, скорее всего, не существует, поэтому после расширения оболочки оно становится:

#!/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, и знаки доллара игнорируются. Обратная сторона: это не сработает, если вам нужно поместить параметры / переменные оболочки в ваш монго-скрипт.

Другой вариант, с которым вы можете поиграть, - связываться со своим шебангом. Например,

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

Есть несколько проблем с этим решением:

  1. Это работает, только если вы пытаетесь сделать скрипт оболочки mongo исполняемым из командной строки. Вы не можете смешивать обычные команды оболочки с командами оболочки Монго. И все, что вы сохраняете при этом, - это не вводить «mongo» в командной строке ... (конечно, достаточно причины)

  2. Он работает точно так же, как «mongo <some-js-file>», что означает, что он не позволяет использовать команду «use <db>».

Я попытался добавить имя базы данных в 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записи вашего Монго запрос:

db.collection.find({"myValue":null}).count();
GSK
источник
13

Как насчет этого:

echo "db.mycollection.findOne()" | mongo myDbName
echo "show collections" | mongo myDbName
Марк Батлер
источник
1
Или немного более читабельно: echo "db.mycollection.findOne ()" | Монго myDbName --quiet | python -m json.tool
dirkaholic
Это полезно для выполнения чего-либо после .mongorcзагрузки ( docs.mongodb.org/manual/reference/program/mongo/… )
Джанфранко П.
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гораздо более надежен, чем echoи позволяет \nпромежуточным командам вводить их в несколько строк.

tgoneil
источник
7
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF
Эрдем ОЗДЕМИР
источник
6

В моем случае, я могу удобно использовать в \nкачестве разделителя для следующей команды Монго, которую я хочу выполнить, затем направить их вmongo

echo $'use your_db\ndb.yourCollection.find()' | mongo
Ardhi
источник
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);})"
Talespin_Kit
источник
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');
mythicalcoder
источник
1
Очень интересно, но не по теме в отношении исходного вопроса.
Jlyonsmith
How to execute mongo commands through shell scripts?Это не по теме. На самом деле я дошел до этого вопроса благодаря названию. Таким людям, как я, полезно читать такой ответ. Кроме того, я даю очень полезный метод в примере, а не игрушечный пример.
Мифический
2

Если вы хотите обработать его одной строкой, это простой способ.

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

cat file.sh | mongo <EXPECTED_COLLECTION>
Эрчин Акчай
источник
1

Я написал различные варианты запуска сценария оболочки Mongo из более крупного сценария Bash.

ДОК
источник
1

Решение для единого сценария оболочки с возможностью передачи аргументов mongo ( --quiet, dbname и т. Д.):

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

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

-SФлаг не может работать на всех платформах.

yǝsʞǝla
источник
0

При использовании репликационного набора записи должны выполняться на ПЕРВИЧНОМ, поэтому я обычно использую синтаксис, подобный этому, чтобы избежать необходимости выяснять, какой хост является главным:

mongo -host myReplicaset/anyKnownReplica

Ричард Солт
источник