Як виконувати команди mongo за допомогою скриптів оболонки?


403

Я хочу виконувати 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, щоб запобігти його завжди підключення до "тесту"
дев

9
Дякую @Gingi - моїм улюбленим методом є mongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()"... simples :)
Метт Флетчер

4
Я б хотів, щоб я отримав ВСІ результати, замість того, щоб побачити, що це просто "введіть його" для більше "
Ренді Л

6
@Amida ви можете зробити, mongo --eval "db.version()" --quietнаприклад, щоб уникнути друку всього шуму, який ви говорите
Фермін Сільва

327

Помістіть сценарій монго у .jsфайл.

Потім виконати mongo < yourFile.js

Наприклад:

demo.js // файл має ваш сценарій

use sample  //db name
show collections

зберегти цей файл у "c: \ db-script"

Потім у cmd-підказці перейдіть до "c: \ db-script"

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
Andrew J

9
@ Matt - Зверніть увагу , що команди без JavaScript , що оболонка забезпечує не доступні в виконуваний файл JavaScript, так use dbNameі show dbsбуде працювати з внутрішньої підказки , але не зсередини оболонкові .jsфайлу. Існують еквіваленти JavaScript для команд, що не належать JavaScript, тому це не обмеження, а лише те, що вам потрібно знати.
Тад Маршалл

4
Якщо вам потрібно вказати ім'я бази даних, ім'я користувача, пароль, ви можете зробити цеmongo dbName -u userName -p "password with spaces" scriptToRun.js
KevinL

1
чи є спосіб тримати підказку mongo відкритою? AKA Я не хочу, щоб монго сказав мені "до побачення".
Олександр Міллс


64

Помістіть це у файл під назвою test.js:

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

потім запустіть його mongo myDbName test.js.


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

Це набагато краще рішення, коли я передаю файл у mongo, я отримую 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
Dennis Münkle

Безумовно, корисно, оскільки ви не можете використовувати "використовувати mydb" у файлі JS.
buzypi

Дякую за це! Нарешті я можу зателефонувати use another_db. :-)
Ionică Bizău

1
Насправді ви можете переключити БД з сценарію mongo: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

Тепер ви можете помістити всі знаки долара у свій гередок, а знаки долара ігнорувати. Нижня сторона: це не працює, якщо вам потрібно ввести сценарій / змінні оболонки в сценарій mongo.

Ще один варіант, з яким можна пограти - це возитися зі своїм шебангом. Наприклад,

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

Існує кілька проблем з цим рішенням:

  1. Він працює лише в тому випадку, якщо ви намагаєтеся зробити скрипт оболонки mongo виконуваним з командного рядка. Ви не можете змішувати звичайні команди оболонки з командами оболонки mongo. І все, що ви економите, роблячи це - не потрібно вводити "монго" в командному рядку ... (звичайно, достатньо причини)

  2. Він функціонує точно так само, як "mongo <some-js-file>", а це означає, що він не дозволяє вам використовувати команду "використовувати <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запису вашого Монго запит:

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


12

Як запропонував theTuxRacer, ви можете використовувати команду eval , для тих, хто її відсутній, як і я, ви також можете додати своє ім'я db, якщо ви не намагаєтеся виконати операцію на db за замовчуванням.

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

7

Дякую printf! У середовищі Linux ось кращий спосіб запустити шоу лише одним файлом. Скажімо, у вас є два файли mongoCmds.jsз декількома командами:

use someDb
db.someColl.find()

а потім файл оболонки драйвера, runMongoCmds.sh

mongo < mongoCmds.js

Натомість майте лише один файл, запустітьMongoCmds.sh, що містить

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

Баш printfнабагато надійніший echoі дозволяє \nміж командами форсувати їх у декількох рядках.



6

У моєму випадку я можу зручно використовувати \nяк роздільник для наступної команди mongo, яку я хочу виконати, а потім передати їхmongo

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

4

- прапор оболонки також можна використовувати для файлів 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?Це не тематично. Насправді я дійшов цього питання через назву. Тож людям, як я, вигідно читати таку відповідь. Також я наводжу дуже корисний метод на прикладі, а не приклад іграшки.
mythicalcoder

2

Якщо ви хочете обробити це одним рядком, це простий спосіб.

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

cat file.sh | mongo <EXPECTED_COLLECTION>


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.