web-dev-qa-db-fra.com

Comment exécuter des commandes mongo à travers des scripts Shell?

Je souhaite exécuter les commandes mongo dans un script Shell, par exemple. dans un script test.sh:

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

Lorsque j'exécute ce script via ./test.sh, la connexion à MongoDB est établie mais les commandes suivantes ne sont pas exécutées.

Comment exécuter d'autres commandes via le script shell test.sh?

352
StackOverFlow

Vous pouvez également évaluer une commande à l'aide de l'indicateur --eval, s'il ne s'agit que d'une seule commande.

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

Remarque: Si vous utilisez des opérateurs Mongo, en commençant par le signe $, vous voudrez entourer l'argument eval de guillemets simples pour empêcher le shell d'évaluer l'opérateur en tant que variable d'environnement:

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

Sinon, vous pouvez voir quelque chose comme ceci:

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

Mettez votre script mongo dans un fichier .js.

Puis exécutez mongo < yourFile.js

Ex:

demo.js // le fichier a votre script

use sample  //db name
show collections

conservez ce fichier dans "c:\db-scripts"

Ensuite, dans l'invite cmd, allez à "c:\db-scripts"

C:\db-scripts>mongo < demo.js

Ceci exécutera le code en Mongo et affichera la sortie

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>
295
Matt

Cela fonctionne pour moi sous Linux:

mongo < script.js
92
Antonin Brettsnajdr

Mettez ceci dans un fichier nommé test.js:

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

puis exécutez-le avec mongo myDbName test.js.

59
Theo

Il existe également une page documentation officielle à ce sujet.

Les exemples de cette page incluent:

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

Le script Shell ci-dessous a également bien fonctionné pour moi. Il était clair que je devais utiliser la redirection mentionnée au début par Antonin ... qui me donna l’idée de tester le document ici.

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

Dans ma configuration, je dois utiliser:

mongo --Host="the.server.ip:port" databaseName theScript.js 
21
Ed Williams

J'utilise la syntaxe "heredoc", que David Young mentionne. Mais il ya un hic:

#!/usr/bin/sh

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

Ce qui précède NE fonctionnera PAS, car la phrase "$ existe" sera vue par le shell et remplacée par la valeur de la variable d'environnement nommée "existe". Ce qui, probablement, n'existe pas, donc après l'expansion de Shell, il devient:

#!/usr/bin/sh

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

Pour le faire passer, vous avez deux options. On est moche, on est assez gentil. Tout d'abord, le vilain: échapper aux signes $:

#!/usr/bin/sh

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

Je ne recommande pas cela, car il est facile d'oublier de s'échapper.

L'autre option est d'échapper à l'EOF, comme ceci:

#!/usr/bin/sh

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

Maintenant, vous pouvez mettre tous les signes du dollar que vous voulez dans votre heredoc, et les signes du dollar sont ignorés. L'inconvénient: cela ne fonctionne pas si vous devez insérer des paramètres/variables du shell dans votre script Mongo.

Une autre option à laquelle vous pouvez jouer est de jouer avec votre Shebang. Par exemple,

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

Il y a plusieurs problèmes avec cette solution:

  1. Cela ne fonctionne que si vous essayez de créer un script shell mongo à partir de la ligne de commande. Vous ne pouvez pas mélanger des commandes Shell régulières avec des commandes Shell mongo. Et tout ce que vous enregistrez en faisant cela n’a pas à taper "mongo" sur la ligne de commande ... (raison suffisante, bien sûr)

  2. Il fonctionne exactement comme "mongo <some-js-file>", ce qui signifie qu'il ne vous permet pas d'utiliser la commande "use <db>".

J'ai essayé d'ajouter le nom de la base de données au Shebang, ce qui pourrait marcher. Malheureusement, de la même manière que le système traite la ligne Shebang, tout ce qui suit le premier espace est transmis à la commande env en tant que paramètre unique (comme s'il était entre guillemets), et env ne parvient pas à le trouver ni à l'exécuter.

Au lieu de cela, vous devez incorporer le changement de base de données dans le script lui-même, comme suit:

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

Comme dans toute vie, "il y a plus d'une façon de le faire!"

18
John Arrowwood

Si vous avez activé l'authentification:

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

Que dis-tu de ça:

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

Comme suggéré par theTuxRacer, vous pouvez utiliser la commande eval; pour ceux qui le manquent comme je le faisais, vous pouvez également ajouter votre nom de base de données si vous n'essayez pas de préformer l'opération sur la base de données par défaut.

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

Créer un fichier de script; écrire des commandes:

#!/bin/sh
mongo < file.js

Dans file.js écrivez votre requête Mongo:

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

Merci printf! Dans un environnement Linux, voici un meilleur moyen de n’avoir qu’un seul fichier pour exécuter le spectacle. Disons que vous avez deux fichiers, mongoCmds.js avec plusieurs commandes:

use someDb
db.someColl.find()

puis le fichier shell du pilote, runMongoCmds.sh

mongo < mongoCmds.js

Au lieu de cela, ayez juste un fichier, runMongoCmds.sh contenant

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

Le printf de Bash est beaucoup plus robuste que echo et permet au \n entre des commandes de les forcer sur plusieurs lignes.

7
tgoneil

--Le drapeau peut également être utilisé pour les fichiers javascript

 mongo --Shell /path/to/jsfile/test.js 
4
Jackson Harry
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"
4
Talespin_Kit
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF
4
Erdem ÖZDEMİR

Dans mon cas, je peux facilement utiliser \n comme séparateur pour la prochaine commande mongo que je veux exécuter, puis les diriger vers mongo

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

Si vous voulez gérer cela avec une seule ligne, c'est un moyen simple.

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

cat file.sh | mongo <EXPECTED_COLLECTION>
2
Erçin Akçay

I écrit les différentes options pour exécuter un script shell Mongo à partir d'un script Bash plus grand

1
PKD

Récemment migré de mongodb vers Postgres. Voici comment j'ai utilisé les scripts.

mongo < scripts.js > inserts.sql

Lisez le scripts.js et la redirection de sortie vers inserts.sql.

scripts.js ressemble à ceci

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 ressemble à ceci

INSERT INTO table(a, b) VALUES('abc', 'Alice'), ('def', 'Bob'), ('ghi', 'Claire');
1
mythicalcoder

Solution de script à un seul shell avec possibilité de passer des arguments mongo (--quiet, nombase, etc.):

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

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

L’indicateur -S risque de ne pas fonctionner sur toutes les plateformes.

0
yǝsʞǝla