MongoDB(二)mongo shell
介绍
mongo shell是一个mongoDB的javascript交互接口。你可以使用mongo shell查询和更新数据,也可以执行管理员操作。
mongo shell是mongoDB的组件,一旦你安装并且启动了mongoDB,你就可以连接mongo shell到mongoDB实例。
启动mongo shell
注意:在试图启用mongo shell前先保证mongoDB已经运行。
去开启mongo shell并且连接到运行在本地的默认端口的mongoDB:
- 在命令提示符下,进入到mongodb安装目录:
cd <mongodb installation dir>
- 输入./bin/mongo来启动mongo:
./bin/mongo
如果你将mongo的路径添加到了系统PATH环境变量里面,那么就可以直接输入mongo来代替./bin/mongo。
选项
如果你在运行mongo的时候没有使用参数,那么mongo shell会尝试连接运行在本地的默认端口27017的mongoDB实例,也可以指定其他域名和端口号,还有更多其他参数,请去查阅mongo手册。
.mongorc.js文件
当启动mongo的时候程序会检查用户的home目录去寻找一个叫做.mongorc.js的文件。如果找到这个文件,mongo会在发出提示之前解释这个文件的内容。如果你想使用mongo shell来对一个javescript文件或者表达式求值,要么使用--eval选项要么指定一个js文件。mongo会在这个js文件或者表达式完成解析之后才去读取.mongorc.js。你可以使用--norc选项来阻止程序读取.mongorc.js文件。
使用mongo shell工作
显示当前正在使用的数据库,使用如下命令:
db
会返回test这个默认的数据库,想切换数据库,使用use <database>:
use <database>
使用show dbs来列出可用的数据库。db.getSiblingDB()方法可以不切换当前数据库环境来获取一个不同的数据库。
你也可以切换到不存在的数据库上去。当你首次在数据库存储数据的时候,例如创建一个collection的时候(collection是一组document,等同于关系数据库的table,document是mongodb的最基本的数据单位),mongoDB就会自动创建这个数据库。下面这个例子会通过inserOne()操作来创建名为myNewDatabase的数据库和名为myCollection的collection:
use myNewDatabase
db.myCollection.insertOne( { x: 1 } );
db.myCollection.insertOne()是一条可用的mongo shell命令。
- db引用当前的数据库
- myCollection是当前collection的名字
如果mongo shell不能接受collection的名字,你可以使用可选的db.getCollection()语法。比如,当一个collection的名字中包含了空格或者连字符,或者以一个数字开头,又或者与一个原生的函数名称冲突:
db.getCollection("3 test").find() db.getCollection("3-test").find() db.getCollection("stats").find()
每一行mongo shell 限制只能有4095个完整的unicode字符。如果你在一行内输入超过了这个限制,那么shell会触发truncate操作。
想要了解更多的mongo shell操作,请去查看官方文档。
格式化打印结果
db.collection.find()方法返回结果的cursor。在mongo shell里,如果返回的cursor没有指派给使用var关键字的变量,随后cursor会自动重复20次来打印最初匹配的20条document。mongo shell会提示Type it来重复另外20次。
在命令后面加上.pretty()可以格式化结果。
db.myCollection.find().pretty()
另外,你可以使用下面明确的打印方法:
- print()普通打印,不格式化。
- print(tojson(<obj>)),json格式化,和printjson()等价。
- printjson(),json格式化,和print(tojson(<obj>))。
更多有关查询cursor的信息请看官方文档。
多行操作
如果你在一行结束的时候使用左圆括号((),或者左花括号({),或者左方括号([),那么下一行就会以省略号开头直到你对应地输入右括号。mongo shell会等待你输入右括号,如下面的例子:
> if ( x > 0 ) { ... count++; ... print (x); ... }
如果连续两行都是空行那么就会退出等待模式:
> if (x > 0 ... ... >
tab键自动补全和其他快捷键
mongo shell支持快捷键,例如:
- 使用方向键上下箭头可以查看历史命令
- 使用tab键来自动补全,例如:
db.myCollection.c<Tab>
因为有很多方法起始字母都是c,所以会列出多个方法。
退出shell
退出shell模式,输入quit()或者使用快捷键ctrl + c
定制提示符
可以通过设置prompt变量来修改提示符的内容。prompt变量可以是字符串也可以是javascript代码。如果它是一个返回字符串的函数,那么每一次提示都会是动态消息。
你可以在.mongorc.js文件里为提示添加逻辑用来在每一次启动mongo shell的时候设置提示符。
定制提示符来显示操作的序号
创建一个拥有当前会话的操作的序号的mongo shell提示符,在mongo shell中定义如下变量:
cmdCount = 1; prompt = function() { return (cmdCount++) + "> "; }
提示符就会类似下面这样:
1> 2> 3>
定制提示符来显示数据库和域名
创建一个类如<database>@<hostname>形式的mongo shell提示,定义如下变量:
host = db.serverStatus().host; prompt = function() { return db+"@"+host+"$ "; }
提示符就会如下所示:
test@myHost1$
定制提示符显示时间和document计数
创建一个包含系统时间和当前数据库中document的数量的提示符,就定义如下变量:
prompt = function() { return "Uptime:"+db.serverStatus().uptime+" Documents:"+db.stats().objects+" > "; }
提示符就会类似下面这样:
Uptime:5897 Documents:6 >
在mongo shell中使用外部编辑器
在启动mongo shell前可以通过设置EDITOR环境变量来在mongo shell中使用你自己想用的编辑器。
export EDITOR=vim
mongo
一旦进入了mongo shell,你可以输入edit <variable> 或者 edit<function>来使用指定的编辑器,如下面的例子:
- 定义一个myFunction()函数:
function myFunction () { }
- 使用自定义编辑器编辑这个函数:
edit myFunction
这条命令会打开vim会话,当编辑完毕后保存并退出vim会话。
- 在mongo shell里,输入myFunction来查看其定义:
myFunction
结果会显示编辑后的变化:
function myFunction() { print("This was edited"); }
当在外部编辑器编辑代码的时候,函数里的代码可能会被修改,取决于javascrip编译器。对mongo来说可能会把1+1变成2或者去除注释。真正的变化只是代码的表面这会因为javascript的版本而改变但是不会改变代码的语义。
改变一次find()查询结果的数量
db.collection.find()方法返回结果的cursor。在mongo shell里,如果返回的cursor没有指派给使用var关键字的变量,随后cursor会自动重复20次来打印最初匹配的20条document。mongo shell会提示Type it来重复另外20次。
可以设置DBQuery.shellBatchSize属性来改变结果的默认数量20,下面的例子将其改为10:
DBQuery.shellBatchSize = 10;
命令行帮助
查看选项列表和开启mongo shell的帮助,在命令行里使用--help选项:
mongo --help
shell帮助
在mongo shell之中查看帮助,输入help:
help
数据库帮助
在mongo shell中:
- 查看服务器上的数据库列表,使用show dbs命令:
show dbs
- 查看对于db对象可用的方法的列表,调用db.help()方法:
db.help()
- 查看shell中一个方法的实现,输入db.<method name>不输入圆括号,例如下面:
db.updateUser
collection帮助
在mongo shell中:
- 查看当前数据库中collection的列表:
show collections
- 查看collection对象上可用的方法或者帮助:
db.collection.help()
此处的collection可以是一个已存在的collection的名字,也可以指定一个不存在的。
- 查看collection方法的实现,输入db.<collection>.<method>不输入圆括号:
db.collection.save
cursor帮助
当在mongo shell中通过find()发放执行read操作的时候,可以使用多个cursor方法修改find()的行为或者通过多个javascript方法去处理find()方法返回的cursor。
- 输入db.collection.find().help()来显示所有可用的修改器和cursor处理方法:
db.collection.find().help()
- 输入db.<collection>.find().<method>来查看方法的具体实现:
db.collection.find().toArray
一些很有用的cursor处理方法:
- hasNext()检查cursor是否有更多的document要返回
- next()返回下一个document并且将cursor位置移向下一个
- foreach(<function>)会重复整个cursor并且对于cursor返回的每一个document应用一个函数,<function>有一个参数代表返回的document。
封装类帮助
想要获取mongo shell中可用的封装类的列表,例如BinData(),输入help misc:
help misc
打开新连接
通过mongo shell或者一个javascript文件,你可以使用mongo()构造器实例化数据库连接:
new Mongo() new Mongo(<host>) new Mongo(<host:port>)
思考下面这个例子,使用getDB()方法在默认端口的localhost上实例化mongoDB实例并且设置全局变量db的值为myDatabase:
conn = new Mongo(); db = conn.getDB("myDatabase");
如果连接到一个mongoDB实例会强制执行访问控制,可以使用db.auth()方法来使之生效。
另外,可以使用connect()方法去连接mongoDB实例。下面的例子连接到了一个运行在localhost上非默认端口27020上的mongoDB实例并且设置了全局变量db:
db = connect("localhost:27020/myDatabase");
交互式mongo和脚本式mongo的区别
当为mongo shell写脚本的时候,考虑下面几点:
- 使用getDB()或者connect()方法来设置全局变量db。可以设置数据库引用到不是db的其他变量上。
- mongo shell里的写操作使用写入安全级别{w:1}作为默认值。如果要执行大量操作,就是用bulk()方法。
- 在javascript文件里不能使用任何shell语句,因为他们不是有效的javascript
下面这张表格显示了与mongo shell语句等价的javascript语句:
show dbs, show databases //db.adminCommand('listDatabases') use <db> //db = db.getSiblingDB('<db>') show collections //db.getCollectionNames() show users //db.getUsers() show roles //db.getRoles({showBuiltinRoles: true}) show log <logname> //db.adminCommand({ 'getLog' : '<logname>' }) show logs //db.adminCommand({ 'getLog' : '*' }) it //cursor = db.collection.find() //if ( cursor.hasNext() ){ // cursor.next(); //}
- 在交互模式下,mongo打印操作的结果时会包含所有cursor的内容。在脚本里,要么使用print()函数,要么使用mongo明确的printjson()函数来返回格式化的JSON数据。
在mongo shell脚本里想要打印所有项在一个结果cursor里,使用下列语法:
cursor = db.collection.find(); while ( cursor.hasNext() ) { printjson( cursor.next() ); }
脚本
在系统命令提示符中,想要执行javascript:
--eval 选项
在mongo shell里使用--eval选项传递一条javascript代码片段,如下所示:
mongo test --eval "printjson(db.getCollectionNames())"
This returns the output of db.getCollectionNames()
using the mongo
shell connected to the mongod
ormongos
instance running on port 27017
on the localhost
interface.
这段代码会使用shell连接运行在默认27017端口上的localhost上的mongod或者mongos返回db.getCollectionNames()的结果。
执行一个javascript文件
你可以为mongo shell指定一个js文件,mongo会立即执行这个js文件,看下面的例子:
mongo localhost:27017/test myjsfile.js
这段操作通过一个连接到test数据库的mongod实例执行了myjsfile.js文件,这个实例运行在localhost端口27017。
你还可以用另一种方法,可以在js文件里使用Mongo()构造器来指定mongodb的连接参数。
可以在shell里使用load()函数,来执行一个js文件:
load("myjstest.js")
load()方法会接受相对路径和绝对路径。如果当前的mongo shell工作目录在/data/db,而myjstest.js在/data/db/scripts目录下,那么下面的操作是等价的:
load("scripts/myjstest.js")
load("/data/db/scripts/myjstest.js")
数据类型
mongodb BSON提供了对于JSON之外的数据类型的支持。driver对这些数据类型在宿主语言中提供了原生支持,mongo shell还提供了几个helper类在javascript shell中支持这些数据类型。
BSON,是一个序列化格式用于储存document并且在mongodb中进行远程程序调用。
Date
mongo shell提供了多种方法来返回日期类型数据date,可以返回字符串也可以返回对象。
- Date()方法返回当前的date为字符串形式
- new Date()构造器返回Date对象被ISODate()包裹
- ISODate()构造器返回Date对象被ISODate()包裹
在内部,Date对象被存储为有符号的64位整型,代表了自从unix时间戳(1970年1月1日)起的毫秒数。
并不是所有的数据库操作和driver都支持完整的64位范围。可以安全地使用不超过0到9999年份范围的date数据。
返回date作为字符串格式
Date()方法返回字符串格式的date:
var myDateString = Date();
输入变量名字以查看其中存的值:
myDateString
Wed Dec 19 2012 01:03:25 GMT-0500 (EST)
使用typeof操作符来核实变量的类型:
typeof myDateString string
返回Date
mongo shell会使用ISODate来包裹Date类型的对象。然而,对象会留下类型Date。
下面的例子使用了new Date()构造器,也使用了ISODate构造器来返回Date对象。
var myDate = new Date(); var myDateInitUsingISODateWrapper = ISODate();
你也可以在使用ISODate的时候使用new操作符。
打印myDate的值,它被包裹在ISODate中:
myDate
ISODate("2012-12-19T06:01:17.171Z")
使用instanceof操作符来核实类型:
myDate instanceof Date myDateInitUsingISODateWrapper instanceof Date
它们都返回了true。