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


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

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>

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
Есть ли способ сохранить приглашение Монго открытым? АКА Я не хочу, чтобы Монго сказал мне "пока".
— Александр Миллс


64

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

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

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


2
Как передать значения в скрипт из bash? Я хочу вставить имя в db, которое доступно в bash как переменную, и я хочу передать его в скрипт (js)
— Sasikanth

Это гораздо лучшее решение: когда я передаю в файл монго, я получаю ошибки синтаксиса js.
— Шторм Мюллер


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


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();

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промежуточным командам вводить их в несколько строк.



6

В моем случае, я могу удобно использовать в \nкачестве разделителя для следующей команды Монго, которую я хочу выполнить, затем направить их в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


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?Это не по теме. На самом деле я дошел до этого вопроса благодаря названию. Таким людям, как я, полезно читать такой ответ. Кроме того, я даю очень полезный метод в примере, а не игрушечный пример.
— Мифический

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Флаг не может работать на всех платформах.


0

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

mongo -host myReplicaset/anyKnownReplica

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.