MongoDB_04
Attribution: MongoDB: The Definitive Guide, Third Edition by Shannon Bradshaw, Eoin Brazil, and Kristina Chodorow (O’Reilly). Copyright 2020 Shannon Bradshaw and Eoin Brazil, 978-1-491-95446-1.
Using the MongoDB Shell
This section covers how to use the shell as part of your command-line toolkit, customize it, and use some of its more advanced functionality.
To connect to a mongod on a different machine or port, specify the hostname, port, and database when starting the shell:
$ mongosh mongodb://127.0.0.1:27017/
MongoDB shell version: 7.0.12
connecting to: some-host:mongodb://127.0.0.1:27017/
>
db
will now refer to *some-host:30000*
’s myDB
database.
Sometimes it is handy to not connect to a mongod at all when starting the mongo shell. If you start the shell with --nodb
, it will start up without attempting to connect to anything:
> mongosh --nodb
Current Mongosh Log ID: 66ae66df0774e613dbc4e49a
Using Mongosh: 2.2.12
Once started, you can connect to a mongod at your leisure by running new Mongo("*
hostname*")
:
> conn = new Mongo("some-host:30000")
connection to some-host:30000
> db = conn.getDB("myDB")
myDB
After these two commands, you can use db
normally. You can use these commands to connect to a different database or server at any time.
Tips for Using the Shell
Because mongo is simply a JavaScript shell, you can get a great deal of help for it by simply looking up JavaScript documentation online.
For MongoDB-specific functionality, the shell includes built-in help that can be accessed by typing help
:
> help
Shell Help:
use Set current database
show 'show databases'/'show dbs': Print a list of all available databases.
'show collections'/'show tables': Print a list of all collections for current database.
'show profile': Prints system.profile information.
'show users': Print a list of all users for current database.
'show roles': Print a list of all roles for current database.
'show log <type>': log for current connection, if type is not set uses 'global'
'show logs': Print all logs.
... ...
Database-level help is provided by db.help()
and collection-level help by db.foo.help()
.
> db.help()
Database Class:
getMongo Returns the current database connection
getName Returns the name of the DB
getCollectionNames Returns an array containing the names of all collections in the current database.
... ...
> db.fooo.help()
Collection Class:
aggregate Calculates aggregate values for the data in a collection or a view.
bulkWrite Performs multiple write operations with controls for order of execution.
count Returns the count of documents that would match a find() query for the collection or view.
... ...
Running Scripts with the Shell
In addition to using the shell interactively, you can also pass the shell JavaScript files to execute. Simply pass in your scripts at the command line:
$ mongosh script1.js script2.js script3.js
I am script1.js
I am script2.js
I am script3.js
The mongosh shell will execute each script listed and exit.
If you want to run a script using a connection to a nondefault host/port mongod, specify the address first, then the script(s):
$ mongosh "mongodb://127.0.0.1:27017/foo" script1.js script2.js script3.js
This would execute the three scripts with db
set to the foo database on some-host:30000.
You can print to stdout in scripts (as the preceding scripts did) using the print function. This allows you to use the shell as part of a pipeline of commands.
You can also run scripts from within the interactive shell using the load
function:
> load("script1.js")
I am script1.js
true
Scripts have access to the db
variable (as well as any other global).
However, shell helpers such as use db
or show collections
do not work from files. There are valid JavaScript equivalents to each of these, as shown in Table.
Helper | Equivalent |
---|---|
use video |
db.getSisterDB("video") |
show dbs |
db.getMongo().getDBs() |
show collections |
db.getCollectionNames() |
You can also use scripts to inject variables into the shell.
For example, you could have a script that simply initializes helper functions that you commonly use. It defines a function, connectTo
, that connects to the locally running database on the given port and sets db
to that connection:
// defineConnectTo.js
/**
* Connect to a database and set db.
*/
var connectTo = function(port, dbname) {
if (!port) {
port = 27017;
}
if (!dbname) {
dbname = "test";
}
db = connect("localhost:"+port+"/"+dbname);
return db;
};
If you load this script in the shell, connectTo
is now defined:
test> typeof connectTo
undefined
test> load('defineConnectTo.js')
true
test> typeof connectTo
function
In addition to adding helper functions, you can use scripts to automate common tasks and administrative activities.
By default, the shell will look in the directory that you started the shell in (use pwd to see what directory that is in Windows cmd or PowerShell ).If the script is not in your current directory, you can give the shell a relative or absolute path to it.
For example, if you wanted to put your shell scripts in ~/my-scripts, you could load defineConnectTo.js with load("/home/myUser/my-scripts/defineConnectTo.js"). Note that load cannot resolve
~
.
Creating a .mongoshrc.js
If you have frequently loaded scripts, you might want to put them in your .mongorc.js file. This file is run whenever you start up the shell.
// .mongoshrc.js
var compliment = ["attractive", "intelligent", "like Saya"];
var index = Math.floor(Math.random()*3);
print("Hello, you're looking particularly "+compliment[index]+" today!");
You should put the mongoshrc.js
file in the /%USERPROFILE%/ (Windows) directory so that when you start mongosh, you’ll see something like:
> mongosh
Current Mongosh Log ID: 66ae758d9edba0e788c4e49a
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.2.12
Using MongoDB: 7.0.12
Using Mongosh: 2.2.12
mongosh 2.2.15 is available for download: https://www.mongodb.com/try/download/shell
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------
The server generated these startup warnings when booting
2024-07-27T16:15:36.491+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
------
Hello, you're looking particularly like Saya today!
>
More practically, you can use this script to set up any global variables you’d like to use, alias long names to shorter ones, and override built-in functions.
One of the most common uses for .mongorc.js is to remove some of the more “dangerous” shell helpers.
You can override functions like dropDatabase
or deleteIndexes
with no-ops or undefine them altogether:
var no = function() {
print("Not on my watch.");
};
// Prevent dropping databases
db.dropDatabase = DB.prototype.dropDatabase = no;
// Prevent dropping collections
DBCollection.prototype.drop = no;
// Prevent dropping an index
DBCollection.prototype.dropIndex = no;
// Prevent dropping indexes
DBCollection.prototype.dropIndexes = no;
Now if you try to call any of these functions, it will simply print an error message. Note that this technique does not protect you against malicious users; it can only help with fat-fingering.
You can disable loading your .mongorc.js by using the
--norc
option when starting the shell.
Customizing Your Prompt
The default shell prompt can be overridden by setting the prompt
variable to either a string or a function.
For example, if you are running a query that takes minutes to complete, you may want to have a prompt that displays the current time so you can see when the last operation finished:
prompt = function() {
return (new Date())+"> ";
};
The .mongorc.js file is a good place to set your prompt if you want to always use a custom one (or set up a couple of custom prompts that you can switch between in the shell).
Inconvenient Collection Names
Fetching a collection with the db.collectionName
syntax almost always works, unless the collection name is a reserved word or is an invalid JavaScript property name.
For example, suppose we are trying to access the version collection. We cannot say db.version
because db.version
is a method on db
(it returns the version of the running MongoDB server):
> db.version
function () {
return this.serverBuildInfo().version;
}
To actually access the version collection, you must use the getCollection function:
> db.getCollection("version")
test.version
This can also be used for collection names with characters that aren’t valid JavaScript property names, such as:
foo-bar-baz and 123abc (JavaScript property names can only contain letters, numbers, $ and _, and cannot start with a number).
Another way of getting around invalid properties is to use array-access syntax. In JavaScript, x.y
is identical to x['y']
.
This means that subcollections can be accessed using variables, not just literal names. Thus, if you needed to perform some operation on every blog subcollection, you could iterate through them with something like this:
test> var collections = ["posts", "comments", "authors"];
test> for (var i in collections) {
... print(db.blog[collections[i]]);
... }
test.blog.posts
test.blog.comments
test.blog.authors
instead of this:
print(db.blog.posts);
print(db.blog.comments);
print(db.blog.authors);
Note that you cannot do db.blog.i, which would be interpreted as test.blog.i, not test.blog.posts. You must use the db.blog[i] syntax for i to be interpreted as a variable.
You can use this technique to access awkwardly named collections:
> var name = "@#&!"
> db[name].find()
Attempting to query db.@#&!
would be illegal, but db[name]
would work.