Come eseguire i comandi di mongo tramite script di shell?


404

Voglio eseguire mongocomandi in shell script, ad esempio in uno script test.sh:

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

Quando eseguo questo script tramite ./test.sh, viene stabilita la connessione a MongoDB, ma i seguenti comandi non vengono eseguiti.

Come eseguire altri comandi tramite script di shell test.sh?

Risposte:


452

Puoi anche valutare un comando usando il --evalflag, se è solo un singolo comando.

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

Nota: se si utilizzano operatori Mongo, a partire da un segno $, è necessario racchiudere l'argomento eval tra virgolette singole per impedire alla shell di valutare l'operatore come variabile di ambiente:

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

Altrimenti potresti vedere qualcosa del genere:

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

35
Per le .find()operazioni, è necessario chiamare un'operazione sull'oggetto risultato per stampare i documenti, come toArray()o shellPrint(). ad es.mongo userdb --eval "printjson(db.users.find().toArray())"
Gingi,

4
Ho dovuto specificare la stringa di connessione come mongo <ip>: <port> / db --eval "printjson (db.serverStatus ())" o mongo <ip>: <port> / db <mongoCommands.js per impedirlo connettersi sempre a "test"
dev

9
Grazie @Gingi - il mio metodo preferito è mongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()"... simples :)
Matt Fletcher il

4
Vorrei ottenere TUTTI i risultati, invece di vederlo uscire "digita" per ""
Randy L

6
@Amida puoi fare mongo --eval "db.version()" --quietad esempio per evitare di stampare tutto il rumore che dici
Fermin Silva,

327

Inserisci il tuo script mongo in un .jsfile.

Quindi eseguire mongo < yourFile.js

Ex:

Il file demo.js // ha il tuo script

use sample  //db name
show collections

mantenere questo file in "c: \ db-scripts"

Quindi nel prompt di cmd vai a "c: \ db-scripts"

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

Questo eseguirà il codice in mongo e mostrerà l'output

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
Abbastanza letteralmente .. prendi esattamente gli stessi comandi che immetteresti nella shell mongo, salverai quei comandi in un .jsfile e lo passerai come parametro al mongocomando.
Matt

7
Vale la pena notare che qualsiasi cosa impostata in un'istruzione --eval (se fornita) all'interprete mongo rimarrà nell'ambito quando lo script (se fornito) viene eseguito. Puoi usarlo per rendere i tuoi script più riutilizzabili, ad es. mongo --eval "somevar = 'someval';" nome_db script_that_uses_somevar.js
Andrew J,

9
@ Matt - Si noti che i comandi non JavaScript che la shell fornisce non sono disponibili in un file JavaScript eseguito, in modo use dbNamee show dbslavorerà dalla shell prompt di interno ma non da all'interno di un .jsfile. Esistono equivalenti JavaScript per i comandi non JavaScript, quindi questa non è una limitazione, solo qualcosa di cui devi essere consapevole.
Tad Marshall,

4
Se devi specificare un nome per un database, un nome utente, una password, puoi farlomongo dbName -u userName -p "password with spaces" scriptToRun.js
KevinL

1
c'è un modo per tenere aperto il prompt di mongo? AKA Non voglio che Mongo mi saluti.
Alexander Mills,


64

Metti questo in un file chiamato test.js:

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

quindi eseguirlo con mongo myDbName test.js.


2
Come passare valori allo script da bash? Voglio inserire il nome in db che è disponibile in bash come variabile e voglio passarlo allo script (js)
Sasikanth,

Questa è una soluzione molto migliore, quando installo un file in mongo ottengo errori di sintassi js.
Storm Muller,

41

C'è anche una pagina di documentazione ufficiale su questo.

Esempi da quella pagina includono:

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

32

Anche lo script della shell di seguito ha funzionato bene per me ... sicuramente ho dovuto usare il reindirizzamento che Antonin ha menzionato all'inizio ... che mi ha dato l'idea di testare il documento qui.

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

13
Bella risposta! Per più comandi, funziona anche:echo -e "use mydb\ndb.leads.findOne()\ndb.leads.find().count()" | mongo
Dennis Münkle

Decisamente utile perché non è possibile utilizzare "usa mydb" all'interno di un file JS.
Buzypi,

Grazie per questo! Finalmente sono in grado di chiamare use another_db. :-)
Ionică Bizău,

1
In realtà puoi cambiare DB dall'interno di uno script mongo:db = db.getSiblingDB('otherdb');
joeytwiddle il

Proprio quello di cui avevo bisogno. Tuttavia, se è necessario utilizzare un solo database, è possibile passare il nome del database al comando mongo, ad es mongo mydb <<EOF.
Ecc

22

Nella mia configurazione devo usare:

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

20

Uso la sintassi "ereditaria", menzionata da David Young. Ma c'è un problema:

#!/usr/bin/sh

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

Quanto sopra NON funzionerà, perché la frase "$ esiste" sarà vista dalla shell e sostituita con il valore della variabile d'ambiente chiamata "esiste". Che, probabilmente, non esiste, quindi dopo l'espansione della shell diventa:

#!/usr/bin/sh

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

Per farlo passare hai due opzioni. Uno è brutto, uno è abbastanza carino. Innanzitutto, il brutto: sfuggire ai segni $:

#!/usr/bin/sh

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

NON lo consiglio, perché è facile dimenticare di scappare.

L'altra opzione è quella di sfuggire all'EOF, in questo modo:

#!/usr/bin/sh

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

Ora puoi mettere tutti i segni del dollaro che vuoi nella tua eredità e i segni del dollaro vengono ignorati. Il lato negativo: non funziona se è necessario inserire parametri / variabili della shell nello script mongo.

Un'altra opzione con cui puoi giocare è quella di pasticciare con il tuo shebang. Per esempio,

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

Esistono diversi problemi con questa soluzione:

  1. Funziona solo se stai provando a rendere eseguibile uno script di shell mongo dalla riga di comando. Non puoi mescolare i normali comandi di shell con i comandi di shell mongo. E tutto ciò che salvi facendo così non è necessario digitare "mongo" sulla riga di comando ... (motivo abbastanza, ovviamente)

  2. Funziona esattamente come "mongo <some-js-file>", il che significa che non ti consente di usare il comando "usa <db>".

Ho provato ad aggiungere il nome del database allo shebang, che penseresti possa funzionare. Sfortunatamente, il modo in cui il sistema elabora la linea shebang, tutto dopo il primo spazio viene passato come un singolo parametro (come se fosse citato) al comando env, e env non riesce a trovarlo ed eseguirlo.

Invece, devi incorporare la modifica del database nello script stesso, in questo modo:

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

Come per qualsiasi cosa nella vita, "c'è più di un modo per farlo!"


18

Nel caso in cui sia abilitata l'autenticazione:

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

16

Creare un file di script; comandi di scrittura:

#!/bin/sh
mongo < file.js

Nella file.jsscrittura la query mongo:

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


12

Come suggerito da theTuxRacer, puoi usare il comando eval , per coloro che lo mancano come me, puoi anche aggiungere il tuo nome db se non stai cercando di preformare l'operazione sul db predefinito.

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

7

Grazie printf! In un ambiente Linux, ecco un modo migliore per avere un solo file per eseguire lo spettacolo. Supponi di avere due file, mongoCmds.jscon più comandi:

use someDb
db.someColl.find()

e quindi il file shell del driver, runMongoCmds.sh

mongo < mongoCmds.js

Invece, avere un solo file, contenente runMongoCmds.sh

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

Bash printfè molto più robusto di echoe consente ai \ncomandi tra di forzarli su più linee.



6

Nel mio caso, posso usare convenientemente \ncome separatore per il prossimo comando mongo che voglio eseguire e poi convogliarlimongo

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

4

--shell flag può anche essere usato per file javascript

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

Penso che questo lasci la shell aperta dopo che js è stato eseguito? mongo /path/to/jsfile/test.jseseguirà anche js.
UpTheCreek

4
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"

3

Migrato di recente da mongodb a Postgres. Ecco come ho usato gli script.

mongo < scripts.js > inserts.sql

Leggi scripts.jse reindirizza l'output a inserts.sql.

scripts.js Somiglia a questo

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 Somiglia a questo

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

1
Molto interessante, ma fuori tema rispetto alla domanda originale.
jlyonsmith,

How to execute mongo commands through shell scripts?Questo non è fuori tema. In effetti, ho raggiunto questa domanda a causa del titolo. Quindi le persone come me traggono beneficio leggendo una simile risposta. Inoltre, sto fornendo un metodo molto utile nell'esempio piuttosto che un esempio di giocattolo.
mythicalcoder

2

Se vuoi gestirlo con una riga è un modo semplice.

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

cat file.sh | mongo <EXPECTED_COLLECTION>

1

Ho scritto le varie opzioni per l'esecuzione di uno script Mongo Shell da uno script Bash più grande


1

Soluzione di script a shell singola con possibilità di passare argomenti mongo ( --quiet, dbname, ecc.):

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

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

La -Sbandiera potrebbe non funzionare su tutte le piattaforme.


0

Quando si utilizza un replicaset, le scritture devono essere eseguite su PRIMARY, quindi di solito utilizzo una sintassi come questa che evita di dover capire quale host è il master:

mongo -host myReplicaset/anyKnownReplica

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.