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

Я хочу выполнить команды монго в сценарии оболочки.

Я попробовал следующий способ test.sh

#!/bin/sh

mongo myDbName

db.mycollection.findOne()

show collections

Когда я выполняю вышеуказанный скрипт./test.sh

Затем соединение Монго установлено, но следующие команды не выполнены

Как выполнить другие команды через скрипт sh [test.sh]?

пожалуйста, помогите мне

23 ответа

Решение

Вы также можете оценить команду, используя --eval флаг, если это всего лишь одна команда.

mongo --eval "printjson(db.serverStatus())"

Обратите внимание: если вы используете операторы Mongo, начиная со знака $, вам нужно заключить аргумент eval в одинарные кавычки, чтобы оболочка не оценивала оператор как переменную среды:

mongo --eval 'db.test.update({"name":"foo"},{$set:{"this":"that"}});'

В противном случае вы можете увидеть что-то вроде этого:

mongo --eval "db.test.update({\"name\":\"foo\"},{$set:{\"this\":\"that\"}});"
> E QUERY    SyntaxError: Unexpected token :

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

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

mongo < script.js

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

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

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

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

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

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

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

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

Если у вас включена аутентификация:

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

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

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

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

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

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

  2. Он работает точно так же, как "mongo ", что означает, что он не позволяет использовать команду "use ".

Я попытался добавить имя базы данных к шебангу, который, как вы думаете, будет работать. К сожалению, то, как система обрабатывает строку Шебанга, все после первого пробела передается в виде отдельного параметра (как в кавычках) команде env, и env не может найти и запустить ее.

Вместо этого вы должны встроить изменение базы данных в сам скрипт, например так:

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

Как и во всем в жизни, "есть более чем один способ сделать это!"

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

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

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

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

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

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

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

Создать файл скрипта; написать команды:

#!/bin/sh
mongo < file.js

В file.js напишите ваш запрос на монго:

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

По предложению theTuxRacer, вы можете использовать команду eval, для тех, кто пропускает ее, как я, вы также можете добавить в свое имя БД, если вы не пытаетесь предварительно выполнить операцию на БД по умолчанию.

mongo <dbname> --eval "printjson(db.something.find())"
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF

Недавно мигрировал из 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');
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"

Флаг --shell также может быть использован для файлов JavaScript

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

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

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

cat file.sh | mongo <EXPECTED_COLLECTION>

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

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

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

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

Устаревшая оболочка mongo была удалена из MongoDB с выпуском версии 6 в 2022 году.

Существует новый способ выполнения сценариев оболочки с использованием новой оболочки mongosh .

Из документации оболочки по написанию скриптов:

  • Вы можете использовать mongosh для выполнения скрипта из командной строки без входа в консоль mongosh .
  • Чтобы указать имя файла, используйте параметр --file или -f, чтобы указать имя файла.
  • Вам также может потребоваться указать информацию о подключении

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

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

mongo -host myReplicaset/anyKnownReplica

Другие вопросы по тегам