Bagaimana cara menjalankan perintah mongo melalui skrip shell?

404

Saya ingin menjalankan mongoperintah dalam skrip shell, misalnya dalam skrip test.sh:

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

Ketika saya menjalankan skrip ini melalui ./test.sh, maka koneksi ke MongoDB dibuat, tetapi perintah berikut ini tidak dijalankan.

Bagaimana cara menjalankan perintah lain melalui skrip shell test.sh?

StackOverFlow
sumber

Jawaban:

452

Anda juga dapat mengevaluasi perintah menggunakan --evalbendera, jika hanya satu perintah.

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

Harap perhatikan: jika Anda menggunakan operator Mongo, dimulai dengan tanda $, Anda harus melingkupi argumen eval dalam tanda kutip tunggal untuk menjaga shell dari mengevaluasi operator sebagai variabel lingkungan:

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

Kalau tidak, Anda mungkin melihat sesuatu seperti ini:

mongo --eval "db.test.update({\"name\":\"foo\"},{$set:{\"this\":\"that\"}});"
> E QUERY    SyntaxError: Unexpected token :
theTuxRacer
sumber
35
Untuk .find()operasi, Anda perlu memanggil operasi pada objek hasil untuk mencetak dokumen, seperti toArray()atau shellPrint(). misalnya,mongo userdb --eval "printjson(db.users.find().toArray())"
Gingi
4
Saya harus menentukan string koneksi seperti mongo <ip>: <port> / db --eval "printjson (db.serverStatus ())" atau mongo <ip>: <port> / db <mongoCommands.js untuk mencegahnya selalu terhubung ke "test"
dev
9
Terima kasih @Gingi - metode pilihan saya adalah mongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()"... simples :)
Matt Fletcher
4
Saya berharap saya akan mendapatkan SEMUA dari hasil, alih-alih melihatnya keluar "ketik 'itu' untuk lebih"
Randy L
6
@Amida dapat Anda lakukan mongo --eval "db.version()" --quietmisalnya untuk menghindari pencetakan semua suara yang Anda katakan
Fermin Silva
327

Masukkan skrip mongo Anda ke dalam .jsfile.

Kemudian jalankan mongo < yourFile.js

Ex:

demo.js // file memiliki skrip Anda

use sample  //db name
show collections

simpan file ini di "c: \ db-scripts"

Kemudian dalam cmd prompt buka "c: \ db-scripts"

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

Ini akan mengeksekusi kode dalam mongo dan menunjukkan 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>
Mat
sumber
13
Secara harfiah .. Anda mengambil perintah yang sama persis dengan yang Anda masukkan ke mongo shell, menyimpan perintah-perintah itu ke .jsfile, dan meneruskannya sebagai parameter ke mongoperintah.
Matt
7
Perlu dicatat apa pun yang Anda tetapkan dalam pernyataan --eval (jika disediakan) ke mongo interpreter akan tetap berada dalam ruang lingkup ketika skrip Anda (jika disediakan) dieksekusi. Anda dapat menggunakan ini membuat skrip Anda lebih dapat digunakan kembali, misalnya. mongo --eval "somevar = 'someval';" db_name script_that_uses_somevar.js
Andrew J
9
@Matt - Perhatikan bahwa perintah non-JavaScript yang disediakan shell tidak tersedia dalam file JavaScript yang dieksekusi, jadi use dbNamedan show dbsakan bekerja dari prompt internal shell tetapi tidak dari dalam .jsfile. Ada persamaan JavaScript untuk perintah non-JavaScript, jadi ini bukan batasan, hanya sesuatu yang perlu Anda ketahui.
Tad Marshall
4
Jika Anda perlu menentukan nama basis data, nama pengguna, kata sandi, Anda dapat melakukannyamongo dbName -u userName -p "password with spaces" scriptToRun.js
KevinL
1
apakah ada cara untuk menjaga mongo prompt tetap terbuka? AKA Saya tidak ingin mongo mengatakan "selamat tinggal" kepada saya.
Alexander Mills
102

Ini berfungsi untuk saya di Linux:

mongo < script.js
Antonin Brettsnajdr
sumber
64

Masukkan ini ke dalam file bernama test.js:

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

kemudian jalankan dengan mongo myDbName test.js.

Theo
sumber
2
Bagaimana cara mengirimkan nilai ke skrip dari bash? Saya ingin memasukkan nama ke db yang tersedia dalam bash sebagai variabel dan saya ingin meneruskannya ke skrip (js)
Sasikanth
Ini adalah solusi yang jauh lebih baik, Ketika saya mem-pipe file ke mongo saya mendapatkan kesalahan sintaks js.
Storm Muller
41

Ada halaman dokumentasi resmi tentang ini juga.

Contoh dari halaman itu termasuk:

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

Script shell di bawah ini juga bekerja dengan baik untuk saya ... pasti harus menggunakan redirect yang disebutkan Antonin pada awalnya ... yang memberi saya ide untuk menguji dokumen di sini.

function testMongoScript {
    mongo <<EOF
    use mydb
    db.leads.findOne()
    db.leads.find().count()
EOF
}
David H. Young
sumber
13
Jawaban bagus! Untuk banyak perintah, ini juga berfungsi:echo -e "use mydb\ndb.leads.findOne()\ndb.leads.find().count()" | mongo
Dennis Münkle
Sangat berguna karena Anda tidak dapat menggunakan "use mydb" dalam file JS.
buzypi
Terima kasih untuk ini! Akhirnya saya bisa menelepon use another_db. :-)
Ionică Bizău
1
Sebenarnya Anda dapat mengganti DB dari dalam skrip mongo:db = db.getSiblingDB('otherdb');
joeytwiddle
Apa yang saya butuhkan. Namun jika Anda hanya perlu menggunakan satu basis data, Anda dapat meneruskan nama basis data ke perintah mongo, mis mongo mydb <<EOF. Dll
spikyjt
22

Dalam pengaturan saya, saya harus menggunakan:

mongo --host="the.server.ip:port" databaseName theScript.js 
Ed Williams
sumber
20

Saya menggunakan sintaks "heredoc", yang David Young sebutkan. Tapi ada yang menangkap:

#!/usr/bin/sh

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

Di atas TIDAK akan berfungsi, karena frasa "$ ada" akan terlihat oleh shell dan diganti dengan nilai variabel lingkungan bernama "ada." Yang, sepertinya, tidak ada, jadi setelah ekspansi shell, itu menjadi:

#!/usr/bin/sh

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

Agar dapat melewati Anda memiliki dua opsi. Satu jelek, satu cukup bagus. Pertama, yang jelek: lepas tanda $:

#!/usr/bin/sh

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

Saya TIDAK merekomendasikan ini, karena mudah lupa untuk melarikan diri.

Opsi lainnya adalah keluar dari EOF, seperti ini:

#!/usr/bin/sh

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

Sekarang, Anda dapat meletakkan semua tanda dolar yang Anda inginkan di heredoc Anda, dan tanda dolar diabaikan. Sisi bawah: Itu tidak berfungsi jika Anda perlu meletakkan parameter / variabel shell di skrip mongo Anda.

Opsi lain yang bisa Anda mainkan adalah mengacaukan shebang Anda. Sebagai contoh,

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

Ada beberapa masalah dengan solusi ini:

  1. Ini hanya berfungsi jika Anda mencoba membuat skrip shell mongo dapat dieksekusi dari baris perintah. Anda tidak dapat mencampur perintah shell biasa dengan perintah shell mongo. Dan semua yang Anda hemat dengan melakukannya adalah tidak harus mengetikkan "mongo" pada baris perintah ... (cukup alasan, tentu saja)

  2. Fungsinya persis seperti "mongo <some-js-file>" yang artinya tidak membiarkan Anda menggunakan perintah "use <db>".

Saya telah mencoba menambahkan nama database ke shebang, yang menurut Anda akan berhasil. Sayangnya, cara sistem memproses garis shebang, semuanya setelah spasi pertama dilewatkan sebagai parameter tunggal (seperti dikutip) ke perintah env, dan env gagal menemukan dan menjalankannya.

Sebagai gantinya, Anda harus menyematkan perubahan database di dalam skrip itu sendiri, seperti:

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

Seperti halnya apa pun dalam hidup, "ada lebih dari satu cara untuk melakukannya!"

John Arrowwood
sumber
18

Jika Anda mengaktifkan otentikasi:

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

Buat file skrip; tulis perintah:

#!/bin/sh
mongo < file.js

Dalam file.jstuliskan mongo query Anda:

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

Bagaimana dengan ini:

echo "db.mycollection.findOne()" | mongo myDbName
echo "show collections" | mongo myDbName
Mark Butler
sumber
1
Atau sedikit lebih mudah dibaca: echo "db.mycollection.findOne ()" | mongo myDbName --quiet | python -m json.tool
dirkaholic
Ini berguna untuk mengeksekusi sesuatu setelah .mongorcdimuat ( docs.mongodb.org/manual/reference/program/mongo/… )
Gianfranco P.
12

Seperti yang disarankan oleh theTuxRacer, Anda dapat menggunakan perintah eval , bagi mereka yang melewatkannya seperti saya, Anda juga dapat menambahkan nama db Anda jika Anda tidak mencoba untuk melakukan operasi sebelumnya pada db default.

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

Terima kasih printf ! Di lingkungan Linux, berikut ini cara yang lebih baik untuk hanya menjalankan satu file saja. Katakanlah Anda memiliki dua file, mongoCmds.jsdengan banyak perintah:

use someDb
db.someColl.find()

dan kemudian file shell driver, runMongoCmds.sh

mongo < mongoCmds.js

Sebagai gantinya, miliki hanya satu file, mengandung runMongoCmds.sh

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

Bash printfjauh lebih kuat daripada echodan memungkinkan \nperintah antara memaksa mereka di beberapa baris.

tgoneil
sumber
7
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF
Erdem ÖZDEMİR
sumber
6

Dalam kasus saya, saya dapat dengan mudah digunakan \nsebagai pemisah untuk perintah mongo berikutnya yang ingin saya jalankan kemudian pipa merekamongo

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

--shell flag juga dapat digunakan untuk file javascript

 mongo --shell /path/to/jsfile/test.js 
Jackson Harry
sumber
Saya pikir ini hanya membiarkan shell terbuka setelah dieksekusi? mongo /path/to/jsfile/test.jsakan exectute js juga.
UpTheCreek
4
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"
Talespin_Kit
sumber
3

Baru-baru ini bermigrasi dari mongodb ke Postgres. Ini adalah bagaimana saya menggunakan skrip.

mongo < scripts.js > inserts.sql

Baca scripts.jsdan hasilkan redirect ke inserts.sql.

scripts.js terlihat seperti ini

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 terlihat seperti ini

INSERT INTO table(a, b) VALUES('abc', 'Alice'), ('def', 'Bob'), ('ghi', 'Claire');
pembuat kode mitos
sumber
1
Sangat menarik, tapi di luar topik yang berkaitan dengan pertanyaan awal.
jlyonsmith
How to execute mongo commands through shell scripts?Ini bukan di luar topik. Sebenarnya, saya mencapai pertanyaan ini karena judulnya. Jadi orang-orang seperti saya mendapat manfaat membaca jawaban seperti itu. Juga, saya memberikan metode yang sangat berguna dalam contoh daripada contoh mainan.
mitos pembuat
2

Jika Anda ingin mengatasinya dengan satu baris, itu cara yang mudah.

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

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

Saya menulis berbagai opsi untuk Menjalankan Skrip Shell Mongo dari dalam skrip Bash yang lebih besar

PKD
sumber
1

Solusi skrip shell tunggal dengan kemampuan menyampaikan argumen mongo ( --quiet, dbname, dll):

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

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

The -Sbendera mungkin tidak bekerja pada semua platform.

yǝsʞǝla
sumber
0

Ketika menggunakan replaset, penulisan harus dilakukan pada PRIMARY, jadi saya biasanya menggunakan sintaksis seperti ini yang menghindari harus mencari tahu host mana yang merupakan master:

mongo -host myReplicaset/anyKnownReplica

Richard Salt
sumber