mongosh는 Node.js REPL (Read Eval Print Loop) 환경에서 돌아가는 쉘이라고 보면 됨.

그러니까 JS 문법을 기반으로 node.js 어지간한 건 다 쓸 수 있고 심지어는 npm 모듈까지 쓸 수 있어서 잘만 쓰면 엄청 편함.

 

 

당장 쉘에서 여러 라인을 사용하려면 외부 에디터나 내장 에디터를 쓰면 되고,

// 외부 에디터
edit

// 내장 에디터
.editor

 

 

여기선 파일로 만들어서 실행시키는 것 위주로 설명함.

 

 

test.js 라는 파일을 만들어 놓고,

print('hello world');

 

 

mongosh에서 실행시키려면 load()를 사용하면 됨.

[direct: mongos] mydb> load('/PATH/TO/test.js')
hello world
true

 

 

 

DB에 값 넣고 빼고 다 할 수 있음.

test.js를 아래처럼 수정하고,

mydb = db.getSiblingDB('mydb');
mydb.mycol.insertMany([
    {
        name: '백충덕',
        lv: 1
    },
    {
        name: '조조',
        lv: 99
    }
]);

 

 

mongosh에서 실행시킨 후 실제로 query해보면 그대로 들어있는 것 확인 가능.

[direct: mongos] mydb> load('/PATH/TO/test.js')
true
[direct: mongos] mydb> db.mycol.find()
[
  { _id: ObjectId('65dd80e2b958ad4033168f4b'), name: '백충덕', lv: 1 },
  { _id: ObjectId('65dd80e2b958ad4033168f4c'), name: '조조', lv: 99 }
]

 

 

load() 할 때 상대경로로도 가능한데 mongosh를 실행한 현재경로로부터의 상대경로이며 mongosh에선 아래처럼 확인 가능

// node.js를 그대로 쓸 수 있다
[direct: mongos] mydb> process.cwd()
/PATH/TO

// test.js 절대경로가 /PATH/TO/test.js 이고 현재경로가 /PATH/TO 이므로 아래처럼 load()도 가능
[direct: mongos] mydb> load('test.js')

 

 

 

node.js를 그대로 쓸 수 있어서 실행결과를 파일로 저장도 가능.

사실 여기서부터 활용도가 넘사벽.

test.js를 아래처럼 수정해서 아까 넣은 데이터를 가져와 파일로 저장.

mydb = db.getSiblingDB('mydb');

const filePath = '/PATH/TO/mycol.json';
mydb.mycol.find().forEach((doc)=>{
    // fs는 built-in 모듈이라 require() 안하고 그냥 써도 됨
    require('fs').appendFileSync(filePath, JSON.stringify(doc)+'\n');
});

 

 

이걸 mongosh에서 load('/PATH/TO/test.js') 로 실행시킨 후 /PATH/TO/mycol.json 파일을 열어보면 직전에 insert 했던 doc들이 한줄씩 저장되어 있는 것을 확인 가능.

cat /PATH/TO/mycol.json
 
{ _id: ObjectId('65dd80e2b958ad4033168f4b'), name: '백충덕', lv: 1 }
{ _id: ObjectId('65dd80e2b958ad4033168f4c'), name: '조조', lv: 99 }

 

 

 

npm 모듈도 다 사용할 수 있으니까 활용도는 무궁무진함.

npm은 global로 설치된 것, 혹은 current working directory의 node_modules에 설치된 것을 사용 가능.

// 테스트용으로 date-fns 설치
cd /PATH/TO
npm install date-fns --save
 
 
 
// test.js
// process.cwd()를 통해 확인하고 process.chdir()로 cwd를 맞게 변경을 해도 require()가 안되길래 그냥 절대경로로 지정했음...
const dateFns = require('/PATH/TO/test.js');
 
print(dateFns.format(new Date(), 'yyyy-MM-dd'));
 
 
 
// mongosh
[direct: mongos] mydb> load('/PATH/TO/test.js')
2024-02-27

 

 

 

 

 

위에서 적은 것처럼 mongosh 안에서 불러서 사용할 수도 있지만,

실제로는 커맨드라인에서 실행해서 필요한 명령들을 실행하거나 데이터를 수집하는 용도로 쓰기 좋음.

그러려면 mongosh의 js 파일을 로드하기 위한 --file 혹은 -f 옵션과 접속/인증을 하지 않는 --nodb 옵션으로 실행하고,

스크립트 내부에서 접속 및 인증을 처리하는 방식이 필요함.

 

아래는 특정 DB의 컬렉션별 docs 카운트를 한 번에 출력해 볼 수 있는 예제.

/PATH/TO/docs_count.js

// config DB와 docs 카운트 출력을 원하는 DB에 모두 접근할 수 있는 사용자 인증을 하거나 혹은 각각 인증 필요
// 여기선 그냥 root 권한 사용자로 인증한다고 가정함
const user = 'root';
const pwd = encodeURIComponent('비밀번호');
const conn = Mongo(`mongodb://${user}:${pwd}@HOSTNAME:PORT`);
const db_config = conn.getDB('config');
 
const DB_NAME = 'mydb';
const db_mydb = conn.getDB(DB_NAME);
 
 
db_config.collections.find().forEach((col) => {
    if (col._id.indexOf(DB_NAME + '.') !== 0) return;
 
    const colName = col._id.split('.')[1];
    const cnt = db_mydb.getCollection(colName).estimatedDocumentCount();
     
    print(`${colName} = ${cnt}`);
});

 

 

이 스크립트를 아래처럼 호출하면 mydb의 컬렉션별 docs 카운트가 출력됨.

/DB_PATH/bin/mongosh --nodb -f /PATH/TO/docs_count.js
 
Current Mongosh Log ID: 65dd8ed336cfbfea538f1f0e
 
Loading file: scripts/test.js
my_col = 633
my_col2 = 717
my_col3 = 1564

 

 

 

mongosh에서 매번 입력해야 했던 저런 단발성 정보확인용 스크립트는 .mongoshrc.js에 snippet처럼 만들어서 호출해도 좋고,

그 외에 주기적으로 실행해서 데이터를 모으거나 하는 용도로도 일일이 뭔가 따로 만들 필요없이 mongosh 실행만으로 가능하니까 활용처는 다양할 듯.

 

 

 

[참고]

https://www.mongodb.com/docs/mongodb-shell/write-scripts/

 

 

 

 

Posted by bloodguy
,