วิธีรันคำสั่ง mongo ผ่านเชลล์สคริปต์


403

ฉันต้องการรันmongoคำสั่งในเชลล์สคริปต์เช่นในสคริปต์test.sh:

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

เมื่อฉันรันสคริปต์นี้ผ่าน./test.shดังนั้นการเชื่อมต่อกับ MongoDB จะถูกสร้างขึ้น แต่คำสั่งต่อไปนี้จะไม่ถูกดำเนินการ

วิธีรันคำสั่งอื่น ๆ ผ่าน shell script 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 เพื่อป้องกันไม่ให้มัน เชื่อมต่อกับ "test" เสมอ
dev

9
ขอบคุณ @Gingi - วิธีที่ฉันชอบคือmongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()"... simples :)
Matt Fletcher

4
ฉันหวังว่าฉันจะได้รับผลลัพธ์ทั้งหมดแทนที่จะได้เห็นมัน "พิมพ์" มันสำหรับอีกต่อไป "
Randy L

6
@Amida คุณสามารถทำmongo --eval "db.version()" --quietเช่นเพื่อหลีกเลี่ยงการพิมพ์เสียงรบกวนทั้งหมดที่คุณพูด
Fermin Silva

327

ใส่สคริปต์ Mongo ของคุณลงใน .jsไฟล์

จากนั้นดำเนินการ mongo < yourFile.js

Ex:

ไฟล์ demo.js // มีสคริปต์ของคุณ

use sample  //db name
show collections

เก็บไฟล์นี้ใน "c: \ db-สคริปต์"

จากนั้นใน cmd prompt ไปที่ "c: \ db-สคริปต์"

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

นี้จะรันรหัสใน mongo และแสดงผลลัพธ์

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 shell, บันทึกคำสั่งเหล่านั้นไปยัง.jsไฟล์, และส่งมันเป็นพารามิเตอร์ไปยังmongoคำสั่ง
Matt

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 ดังนั้นนี่ไม่ใช่ข้อ จำกัด สิ่งที่คุณต้องระวัง
Tad Marshall

4
หากคุณต้องการระบุชื่อของฐานข้อมูลชื่อผู้ใช้รหัสผ่านคุณสามารถทำได้mongo dbName -u userName -p "password with spaces" scriptToRun.js
KevinL

1
มีวิธีให้เปิด mongo หรือไม่ AKA ฉันไม่ต้องการ Mongo ที่จะพูดว่า "บาย" กับฉัน
Alexander Mills


64

วางสิ่งนี้ลงในไฟล์ชื่อtest.js:

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

mongo myDbName test.jsแล้วเรียกมันด้วย


2
วิธีการส่งผ่านค่าไปยังสคริปต์จากทุบตี? ฉันต้องการที่จะใส่ชื่อลงในฐานข้อมูลที่มีอยู่ในทุบตีเป็นตัวแปรและฉันต้องการที่จะผ่านมันไปยังสคริปต์ (js)
Sasikanth

นี่เป็นวิธีที่ดีกว่ามากเมื่อฉันส่งไฟล์ไปยัง Mongo ฉันได้รับข้อผิดพลาดทางไวยากรณ์ js
Storm Muller


32

สคริปต์เชลล์ด้านล่างใช้งานได้ดีสำหรับฉัน ... แน่นอนต้องใช้การเปลี่ยนเส้นทางที่ Antonin พูดถึงในตอนแรก ... ซึ่งทำให้ฉันมีความคิดที่จะทดสอบเอกสารที่นี่

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
ที่จริงคุณสามารถสลับ DB จากภายในสคริปต์ Mongo นี้:db = db.getSiblingDB('otherdb');
joeytwiddle

สิ่งที่ฉันต้องการ อย่างไรก็ตามหากคุณต้องการใช้เพียงหนึ่งฐานข้อมูลคุณสามารถส่งชื่อฐานข้อมูลไปยังคำสั่ง mongo mongo mydb <<EOFเป็นต้น
spikyjt


20

ฉันใช้ไวยากรณ์ "heredoc" ซึ่ง David Young กล่าวถึง แต่มีการจับ:

#!/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 ของคุณ

อีกทางเลือกหนึ่งที่คุณสามารถเล่นได้คือยุ่งกับ shebang ของคุณ ตัวอย่างเช่น,

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

มีปัญหาหลายอย่างในการแก้ปัญหานี้:

  1. ใช้งานได้เฉพาะในกรณีที่คุณพยายามสร้างเชลล์สคริปต์ mongo จากบรรทัดคำสั่ง คุณไม่สามารถผสมคำสั่งเชลล์ปกติกับคำสั่งเชลล์ mongo และสิ่งที่คุณบันทึกด้วยการทำเช่นนั้นไม่ต้องพิมพ์ "mongo" ในบรรทัดคำสั่ง ... (เหตุผลเพียงพอแน่นอน)

  2. มันทำงานเหมือนกับ "mongo <some-js-file>" ซึ่งหมายความว่ามันจะไม่ยอมให้คุณใช้คำสั่ง "use <dput"

ฉันได้ลองเพิ่มชื่อฐานข้อมูลลงใน shebang ซึ่งคุณคิดว่าจะใช้งานได้ น่าเสียดายที่วิธีการที่ระบบประมวลผลบรรทัด shebang ทุกอย่างหลังจากที่เว้นวรรคแรกถูกส่งผ่านเป็นพารามิเตอร์เดียว (ราวกับว่าที่ยกมา) กับคำสั่ง env และ env ล้มเหลวในการค้นหาและเรียกใช้

คุณต้องฝังการเปลี่ยนแปลงฐานข้อมูลภายในสคริปต์แทนเช่น:

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

เช่นเดียวกับสิ่งใดในชีวิต "มีมากกว่าหนึ่งวิธีที่จะทำ!"



16

สร้างไฟล์สคริปต์ เขียนคำสั่ง:

#!/bin/sh
mongo < file.js

ในการfile.jsเขียนแบบสอบถาม Mongo ของคุณ:

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

13

เกี่ยวกับสิ่งนี้:

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

1
หรืออ่านเพิ่มเติมได้อีกเล็กน้อย: echo "db.mycollection.findOne ()" | mongo myDbName --quiet | python -m json.tool
dirkaholic

สิ่งนี้มีประโยชน์ในการเรียกใช้งานบางอย่างหลังจาก.mongorcโหลดแล้ว ( docs.mongodb.org/manual/reference/program/mongo/ … )
Gianfranco P.

12

ตามที่แนะนำโดยtheTuxRacerคุณสามารถใช้คำสั่งevalสำหรับผู้ที่ขาดหายไปเหมือนฉันคุณสามารถเพิ่มชื่อ db ของคุณหากคุณไม่พยายาม preform การดำเนินการในฐานข้อมูลเริ่มต้น

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

7

ขอขอบคุณprintf! ในระบบลีนุกซ์นี่เป็นวิธีที่ดีกว่าที่จะมีไฟล์เพียงไฟล์เดียวที่แสดงโชว์ สมมติว่าคุณมีสองไฟล์โดยmongoCmds.jsมีหลายคำสั่ง:

use someDb
db.someColl.find()

จากนั้นไฟล์เชลล์ของไดรเวอร์ runMongoCmds.sh

mongo < mongoCmds.js

มีเพียงไฟล์เดียวที่มี runMongoCmds.sh แทน

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

Bash's printfนั้นแข็งแกร่งกว่าechoและอนุญาตให้\nคำสั่งระหว่างคำสั่งบังคับมันได้หลายบรรทัด



6

ในกรณีของฉันฉันสามารถใช้\nเป็นตัวคั่นสำหรับคำสั่ง mongo ถัดไปที่ฉันต้องการเรียกใช้จากนั้นก็ไพพ์ไปยังmongo

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

4

- ธงเปลือกสามารถใช้สำหรับไฟล์จาวาสคริปต์

 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

เมื่อใช้ replicaset การเขียนจะต้องทำบน primary ดังนั้นฉันมักจะใช้ไวยากรณ์เช่นนี้เพื่อหลีกเลี่ยงการคิดว่าโฮสต์ใดเป็นมาสเตอร์:

mongo -host myReplicaset/anyKnownReplica

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.