Làm thế nào để thực thi các lệnh mongo thông qua các kịch bản shell?


404

Tôi muốn thực thi mongocác lệnh trong shell script, ví dụ như trong một kịch bản test.sh:

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

Khi tôi thực thi tập lệnh này thông qua ./test.sh, thì kết nối đến MongoDB được thiết lập, nhưng các lệnh sau không được thực thi.

Làm thế nào để thực thi các lệnh khác thông qua shell script test.sh?

Câu trả lời:


452

Bạn cũng có thể đánh giá một lệnh bằng cách sử dụng --evalcờ, nếu đó chỉ là một lệnh duy nhất.

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

Xin lưu ý: nếu bạn đang sử dụng các toán tử Mongo, bắt đầu bằng dấu $, bạn sẽ muốn bao quanh đối số eval trong các dấu ngoặc đơn để giữ cho shell không đánh giá toán tử dưới dạng biến môi trường:

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

Nếu không, bạn có thể thấy một cái gì đó như thế này:

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

35
Đối với các .find()thao tác, bạn cần gọi một thao tác trên đối tượng kết quả để in các tài liệu, chẳng hạn như toArray()hoặc shellPrint(). ví dụ:mongo userdb --eval "printjson(db.users.find().toArray())"
Gingi

4
Tôi đã phải chỉ định chuỗi kết nối như mongo <ip>: <port> / db --eval "printjson (db.serverStatus ())" hoặc mongo <ip>: <port> / db <mongoCommands.js để ngăn chặn nó khỏi luôn luôn kết nối với "kiểm tra"
dev

9
Cảm ơn @Gingi - phương pháp ưa thích của tôi là mongo mydb --eval "db.users.find({a:'b'}).pretty().shellPrint()"... simples :)
Matt Fletcher

4
tôi ước tôi sẽ nhận được TẤT CẢ các kết quả, thay vì nhìn thấy nó "gõ" nó để biết thêm "
Randy L

6
@Amida bạn có thể làm mongo --eval "db.version()" --quietví dụ để tránh in tất cả tiếng ồn bạn nói
Fermin Silva

327

Đặt tập lệnh mongo của bạn vào một .jstập tin.

Sau đó thực hiện mongo < yourFile.js

Ví dụ:

tập tin demo.js // có tập lệnh của bạn

use sample  //db name
show collections

giữ tệp này trong "c: \ db-scripts"

Sau đó, trong dấu nhắc cmd, hãy chuyển đến "c: \ db-scripts"

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

Điều này sẽ thực thi mã trong mongo và hiển thị đầu ra

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
Theo đúng nghĩa đen .. bạn thực hiện chính xác các lệnh bạn sẽ nhập vào trình vỏ mongo, lưu các lệnh đó vào một .jstệp và chuyển nó dưới dạng tham số cho mongolệnh.
Matt

7
Đáng chú ý bất cứ điều gì bạn đặt trong một câu lệnh --eval (nếu được cung cấp) cho trình thông dịch mongo sẽ vẫn ở trong phạm vi khi tập lệnh của bạn (nếu được cung cấp) được thực thi. Bạn có thể sử dụng điều này làm cho tập lệnh của bạn có thể tái sử dụng nhiều hơn, vd. mongo --eval "somevar = 'someval';" db_name script_that_uses_somevar.js
Andrew J

9
@Matt - Lưu ý rằng các lệnh không phải JavaScript mà shell cung cấp không có sẵn trong tệp JavaScript đã thực thi, do đó use dbNameshow dbssẽ hoạt động từ dấu nhắc bên trong của shell nhưng không phải từ bên trong .jstệp. Có các tương đương JavaScript cho các lệnh không phải JavaScript, vì vậy đây không phải là giới hạn, chỉ là điều bạn cần lưu ý.
Tad Marshall

4
Nếu bạn cần chỉ định tên của cơ sở dữ liệu, tên người dùng, mật khẩu, bạn có thể làmmongo dbName -u userName -p "password with spaces" scriptToRun.js
KevinL

1
Có cách nào để giữ dấu nhắc mongo mở không? AKA Tôi không muốn mongo nói "tạm biệt" với tôi.
Alexander Mills


64

Đặt cái này trong một tập tin gọi là test.js:

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

sau đó chạy nó với mongo myDbName test.js.


2
Làm thế nào để truyền giá trị cho tập lệnh từ bash? Tôi muốn chèn tên vào db có sẵn trong bash dưới dạng biến và tôi muốn chuyển nó sang tập lệnh (js)
Sasikanth

Đây là một giải pháp tốt hơn nhiều, Khi tôi chuyển một tệp sang mongo, tôi gặp lỗi cú pháp js.
Bão Muller

41

Có một trang tài liệu chính thức về điều này là tốt.

Ví dụ từ trang đó bao gồm:

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

32

Kịch bản shell bên dưới cũng hoạt động tốt đối với tôi ... chắc chắn phải sử dụng chuyển hướng mà Antonin đã đề cập lúc đầu ... điều đó cho tôi ý tưởng để kiểm tra tài liệu ở đây.

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

13
Câu trả lời chính xác! Đối với nhiều lệnh, điều này cũng hoạt động:echo -e "use mydb\ndb.leads.findOne()\ndb.leads.find().count()" | mongo
Dennis Münkle

Chắc chắn hữu ích vì bạn không thể sử dụng "use mydb" trong tệp JS.
buzypi

Cảm ơn vì điều này! Cuối cùng tôi cũng có thể gọi use another_db. :-)
Ionică Bizău

1
Trên thực tế, bạn có thể chuyển đổi DB từ trong một tập lệnh mongo:db = db.getSiblingDB('otherdb');
joeytwiddle

Đúng thứ tôi cần. Tuy nhiên, nếu bạn chỉ cần sử dụng một cơ sở dữ liệu, bạn có thể chuyển tên cơ sở dữ liệu cho lệnh mongo, mongo mydb <<EOFv.v.
spikyjt

22

Trong thiết lập của tôi, tôi phải sử dụng:

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

20

Tôi sử dụng cú pháp "heredoc", mà David Young đề cập. Nhưng có một nhược điểm:

#!/usr/bin/sh

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

Ở trên sẽ KHÔNG hoạt động, bởi vì cụm từ "$ tồn tại" sẽ được nhìn thấy bởi shell và được thay thế bằng giá trị của biến môi trường có tên "tồn tại". Mà, có khả năng, không tồn tại, vì vậy sau khi mở rộng vỏ, nó trở thành:

#!/usr/bin/sh

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

Để có nó đi qua bạn có hai lựa chọn. Một là xấu xí, một là khá tốt đẹp. Đầu tiên, cái xấu nhất: thoát khỏi dấu $:

#!/usr/bin/sh

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

Tôi KHÔNG khuyên bạn điều này, vì nó rất dễ quên để trốn thoát.

Tùy chọn khác là thoát EOF, như thế này:

#!/usr/bin/sh

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

Bây giờ, bạn có thể đặt tất cả các ký hiệu đô la bạn muốn trong di sản của mình và các ký hiệu đô la bị bỏ qua. Mặt trái: Điều đó không hoạt động nếu bạn cần đặt các tham số / biến shell trong tập lệnh mongo của mình.

Một lựa chọn khác bạn có thể chơi với là gây rối với shebang của bạn. Ví dụ,

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

Có một số vấn đề với giải pháp này:

  1. Nó chỉ hoạt động nếu bạn đang cố gắng tạo một kịch bản shell mongo có thể thực thi được từ dòng lệnh. Bạn không thể trộn các lệnh shell thông thường với các lệnh shell mongo. Và tất cả những gì bạn lưu bằng cách làm như vậy là không phải gõ "mongo" trên dòng lệnh ... (tất nhiên là đủ lý do)

  2. Nó hoạt động chính xác như "mongo <some-js-file>" có nghĩa là nó không cho phép bạn sử dụng lệnh "use <db>".

Tôi đã thử thêm tên cơ sở dữ liệu vào shebang, cái mà bạn nghĩ sẽ hoạt động. Thật không may, cách hệ thống xử lý dòng shebang, mọi thứ sau khi khoảng trống đầu tiên được truyền dưới dạng một tham số duy nhất (như được trích dẫn) cho lệnh env và env không tìm thấy và chạy nó.

Thay vào đó, bạn phải nhúng thay đổi cơ sở dữ liệu trong chính tập lệnh, như vậy:

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

Như với bất cứ điều gì trong cuộc sống, "có nhiều hơn một cách để làm điều đó!"


18

Trong trường hợp bạn đã bật xác thực:

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

16

Tạo một tập tin kịch bản; viết lệnh:

#!/bin/sh
mongo < file.js

Trong file.jsviết truy vấn mongo của bạn:

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


12

Theo đề xuất của theTuxRacer, bạn có thể sử dụng lệnh eval , đối với những người thiếu nó như tôi, bạn cũng có thể thêm vào tên db của mình nếu bạn không cố gắng tạo ra hoạt động trên db mặc định.

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

7

Cảm ơn bạn printf! Trong môi trường Linux, đây là cách tốt hơn để chỉ có một tệp chạy chương trình. Giả sử bạn có hai tệp, mongoCmds.jsvới nhiều lệnh:

use someDb
db.someColl.find()

và sau đó tập tin trình điều khiển shell, runMongoCmds.sh

mongo < mongoCmds.js

Thay vào đó, chỉ có một tệp, runMongoCmds.sh có chứa

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

Bash's printfmạnh hơn nhiều so với echovà cho phép các \nlệnh giữa buộc chúng trên nhiều dòng.



6

Trong trường hợp của tôi, tôi có thể thuận tiện sử dụng \nlàm dấu phân cách cho lệnh mongo tiếp theo mà tôi muốn thực hiện sau đó chuyển chúng sangmongo

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

4

--shell flag cũng có thể được sử dụng cho các tệp javascript

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

Tôi nghĩ rằng điều này chỉ để lại vỏ mở sau khi js thực hiện? mongo /path/to/jsfile/test.jssẽ thực hiện js quá.
UpTheCux

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

3

Gần đây đã di chuyển từ mongodb đến Postgres. Đây là cách tôi sử dụng các kịch bản.

mongo < scripts.js > inserts.sql

Đọc scripts.jsvà chuyển hướng đầu ra đến inserts.sql.

scripts.js trông như thế này

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 trông như thế này

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

1
Rất thú vị, nhưng lạc đề về câu hỏi ban đầu.
jlyonsmith

How to execute mongo commands through shell scripts?Đây không phải là lạc đề. Trong thực tế, tôi đã đạt được câu hỏi này do tiêu đề. Vì vậy, những người như tôi có lợi khi đọc một câu trả lời như vậy. Ngoài ra, tôi đang đưa ra một phương pháp rất hữu ích trong ví dụ chứ không phải là một ví dụ đồ chơi.
huyền thoại mã hóa

2

Nếu bạn muốn xử lý nó với một dòng thì đó là một cách dễ dàng.

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

cat file.sh | mongo <EXPECTED_COLLECTION>

1

Tôi đã viết lên các tùy chọn khác nhau để Chạy Tập lệnh Mongo Shell trong tập lệnh Bash lớn hơn


1

Giải pháp tập lệnh shell đơn với khả năng truyền các đối số mongo ( --quiet, dbname, v.v.):

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

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

Các -Slá cờ có thể không hoạt động trên tất cả các nền tảng.


0

Khi sử dụng một bản sao, việc ghi phải được thực hiện trên PRIMARY, vì vậy tôi thường sử dụng cú pháp như thế này để tránh phải tìm ra máy chủ nào là chủ:

mongo -host myReplicaset/anyKnownReplica

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.