MongoDB
定位
MongoDB的写入性能是比较差,因为全局锁+mmap的磁盘IO处理方式,线上测试情况, 每秒只能在200~300次的写入(UPS)性能,这样的一个特性决定了它更适合做离线业务, 在线业务方面很多项目都吃亏很多(包括我们之前项目)。比较好的解决方案是采用 TokuMX发行版来替换原生MongoDB,写入性能能够提升20~30倍
文档 > 集合 > 数据库
管理
帮助文件
-
在客户端中输入
help
查看Shell的帮助文档。 -
使用
db.help()
查看数据库级别的帮助文档。 -
使用
db.集合名称.help()
查看集合相关的文档。 -
输入函数时不输入
()
,就可以查看函数的源代码,了解细节了。 -
在
http://api.mongodb.org/js
可以看到Shell相关的JavaScript函数API。
启动服务
#!/bin/bash cd /opt/morganstudio/database/mongodb bin/mongod --dbpath /media/file-data/mongodb-data/data --logfile /var/mongo.log
默认监听27017
端口,28017
也有HTTP服务可以查看服务状态。
以修复模式启动
mongod --repair
实际很可能数据库数据损坏或数据状态不一致,导致无法正常启动MongoDB服务器,根据 启动信息可以看到需要进行修复。或者执行:
mongod -f /etc/mongodb.conf --repair
以认证模式启动
- 和用户管理相关的操作基本都要在admin数据库下运行,要先use admin;
- 如果在某个单一的数据库下,那只能对当前数据库的权限进行操作;
- db.addUser是老版本的操作,现在版本也还能继续使用,创建出来的user是带有root role的超级管理员。
添加用户
use admin db.createUser( { user: "buru", pwd: "12345678", roles: [{role: "userAdminAnyDatabase", db: "admin"}] })
切换到admin下,查看刚才创建的用户:
show users // 或 db.system.users.find()
重启mongo服务
怎么关闭 mongoDB?千万不要kill -9 pid
,可以kill -2 pid
或
db.shutdownServer()
下面使用 –auth 参 数,重新启动 mongoDB:
mongod --auth -f mongodb-linux-i686-3.0.0/mongodb.conf
以验证方式登录
再次打开 mongo shell:
mongo use admin db.auth("buru","12345678") #认证,返回1表示成功 或 mongo -u buru -p 12345678 --authenticationDatabase admin
此时show collections
报错,因为没有权限。用户buru只有「用户管理」的权限。
创建普通用户
下面创建用户,用户都跟着库走,创建的用户都是
use databaseName1 db.createUser({user: "bao", pwd: "12345678", roles: [{role: "readWrite", db: "databaseName1" }] }) use databaseName2 db.createUser({ user: "bao", pwd: "12345678", roles: [{role: "read", db: "databaseName2" },] }) use databaseName3 db.createUser({ user: "bao", pwd: "12345678", roles: [{role: "dbOwner" }] }) use databaseName2 db.createUser({user: "bao",pwd: "12345678", roles: [{role: "root" }] })
查看刚刚创建的用户。
show users { "_id" : "tianhe.bao", "user" : "bao", "db" : "tianhe", "roles" : [ { "role" : "readWrite", "db" : "tianhe" }, { "role" : "read", "db" : "tianhe2" } ] }
查看整个mongoDB全部的用户:
use admin db.system.users.find() { "_id" : "admin.buru", "user" : "buru", "db" : "admin", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "gwVwuA/dXvxgSHavEnlyvA==", "storedKey" : "l2QEVTEujpkCuqDEKqfIWbSv4ms=", "serverKey" : "M1ofNKXg2sNCsFrBJbX4pXbSgvg=" } }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] } { "_id" : "tianhe.bao", "user" : "bao", "db" : "tianhe", "credentials" : { "SCRAM-SHA-1" : { "iterationCount" : 10000, "salt" : "//xy1V1fbqEHC1gzQqZHGQ==", "storedKey" : "ZS/o54zzl/FdcXLQJ98KdAVTfF0=", "serverKey" : "iIpNYz2Gk8KhyK3zgz6muBt0PI4=" } }, "roles" : [ { "role" : "readWrite", "db" : "tianhe" }, { "role" : "read", "db" : "tianhe2" } ] }
切换到对应的用户
先auth:
db.auth("bao","12345678") 或 mongo -u bao -p 12345678 --authenticationDatabase admin
创建一个不受访问限制的超级用户
use admin db.createUser({user:"superuser", pwd:"pwd", roles:["root"]})
修改密码
use admin db.changeUserPassword("username", "xxx")
查看用户信息
db.runCommand({usersInfo:"userName"})
修改密码和用户信息
db.runCommand({updateUser:"username", pwd:"xxx", customData:{title:"xxx"}})
终止服务器进程
db.shutdownServer()
终止数据库服务器进程。或者,可以直接kill掉mongod进程即可。
备份
1、备份全部数据库
mkdir testbak cd testbak mongodump 说明:默认备份目录及数据文件格式为./dump/[databasename]/[collectionname].bson
2、备份指定数据库
mongodump -d pagedb
说明:备份数据库pagedb中的数据。
3、备份一个数据库中的某个集合
mongodump -d pagedb -c page
说明:备份数据库pagedb的page集合。
4、恢复全部数据库
cd testbak mongorestore --drop
说明:将备份的所有数据库恢复到数据库,--drop
指定恢复数据之前删除原来数据库数据
,否则会造成回复后的数据中数据重复。
5、恢复某个数据库的数据
mongorestore --drop -d pagedb --directoryperdb ./dump/pagedb
说明:将备份的pagedb的数据恢复到数据库。
6、恢复某个数据库的某个集合的数据
cd testbak mongorestore --drop -d pagedb -c page --directoryperdb ./dump/pagedb
说明:将备份的pagedb的的page集合的数据恢复到数据库。
7、向MongoDB导入数据
mongoimport -d pagedb -c page --type csv --headerline --drop < csvORtsvFile.csv
说明:将文件csvORtsvFile.csv
的数据导入到pagedb数据库的page集合中,
使用cvs或tsv文件的列名作为集合的列名。需要注意的是,使用--headerline
选项时,
只支持csv和tsv文件。
--type
支持的类型有三个:csv、tsv、json
具体查看mongoimport --help
8、从向MongoDB导出数据
mongoexport -d pagedb -c page -q {} -f _id,title,url,spiderName,pubDate \ --csv > pages.csv
说明:将pagedb数据库中page集合的数据导出到pages.csv文件,其中各选项含义:
-
-f
指定cvs列名为_id
,title
,url
,spiderName
,pubDate
-
-q
指定查询条件
注意: 如果上面的选项-q指定一个查询条件,需要使用单引号括起来,如下所示:
mongoexport -d page -c Article -q '{"spiderName": "mafengwoSpider"}' \ -f _id,title,content,images,publishDate,spiderName,url \ --jsonArray > mafengwoArticle.txt
具体查看帮助:mongoexport --help
登录
#!/bin/bash /opt/morganstudio/database/mongodb/bin/mongo mysql.local-vm:27017
默认连接test
数据库。client中通过help
查看最顶层的帮助文档:
> help HELP Show dbs 显示数据库名 show collections 显示当前数据库中的集合集 show users 显示当前数据库的用户 show profile 显示最后系统用时大于1ms的系统概要 use <db name> 切换到数据库 db.help() help on DB methods db.foo.help() help on collection methods db.foo.find() list objects in collection foo db.foo.find({a : 1}) list objects in foo where a == 1 it 迭代下一页记录
带用户名与密码:
mongo -u admin -p admin 192.168.0.197:27017/pagedb
基于MongoDB支持的javascript实现远程连接
当你已经连接到一个远程的MongoDB数据库服务器 (例如,通过mongo连接到192.168.0.184), 现在想要在这个会话中连接另一个远程的数据库服务器(192.168.0.197), 可以执行如下命令:
var x = new Mongo('192.168.0.197:27017') var ydb = x.getDB('pagedb'); use ydb ydb.page.findOne()
上述通过MongoDB提供的JavaScript脚本,实现对另一个远程数据库服务器进行连接, 操作指定数据库pagedb的page集合。
如果启用了安全认证模式,可以在获取数据库连接实例时,指定认证账号,例如:
var x = new Mongo('192.168.0.197:27017') var ydb = x.getDB('pagedb', 'shirdrn', '(jkfFS$343$_\=\,.F@3'); use ydb
数据库操作
基础操作
查看帮助:
db.help()
显示当前数据库服务器上的数据库
show dbs
切换数据库(如果数据库不存在直接创建):
use dbName
查看数据库服务器的状态:
db.serverStatus()
查询指定数据库统计信息
use fragment db.stats()
查询指定数据库的集合当前可用的存储空间
db.baseSe.storageSize()
查询指定数据库的集合分配的存储空间
db.baseSe.totalSize()
删除数据库
db.dropDatabase()
修复数据库
db.repairDatabase()
设置记录profiling,0=off
, 1=slow
,2=all
db.setProfilingLevel(1)
查看profiling
show profile
拷贝数据库
db.copyDatabase('mail_addr','mail_addr_tmp')
加锁
不允许执行写数据操作,一般在执行数据库备份时有用。
db.runCommand({fsync:1,lock:1}) { "info" : "now locked against writes, use db.$cmd.sys.unlock.findOne() to unlock", "ok" : 1 }
查看当前锁状态
db.currentOp() { "inprog" : [ ], "fsyncLock" : 1, "info" : "use db.$cmd.sys.unlock.findOne() to terminate the fsync write/snapshot lock" }
返回信息中的fsyncLock
为1表示MongoDB的fsync进程(负责将写入改变同步到磁盘)
不允许其他进程执行写数据操作
解锁
use admin db.$cmd.sys.unlock.findOne()
集合操作
显示数据库中所有的集合(collection)
show collections
询指定数据库包含的集合名称列表
db.getCollectionNames()
成员访问
通过.
直接访问数据库的成员,先找成员,没有再返回集合。:
db.version // version成员方法 db.blog // blog集合
通过getCollection("collectionName")
方法,只取得集合:
db.version // version集合,不是方法
遍历集合,因为JavaScript中x.y
与x['y']
等价,所以:
var collection = ["aa","bb","cc"]; for (i in collections) { doStuff(db.blog[collections[i]]) }
而不是:
doStuff(db.blog.aa); doStuff(db.blog.bb); doStuff(db.blog.cc);
成员方法
查看集合帮助
db.songs.help();
查看所有集合的状态
db.printCollectionStats();
查看当前集合状态
db.music.stats();
集合重命名
db.music.renameCollection("musics");
查看集合总数据量
db.songs.count();
查看表空间大小
db.songs.dataSize();
查看集合所在数据库
db.songs.getDB();
创建集合(集合中必须产生过数据)
db.music; db.music.insert({"id":1,"name":"love","orders":1}); db.music.count();
集合复制
db.musics.copyTo("music");
删除集合
db.musics.drop();
清空集合
db.musics.remove();
重命名字段
db.musics.update({}, {$rename : {"id" : "m_id"}}, false, true);
查看不存在id字段的文档数量
db.musics.find({"id":{$exists:false}}).count();; db.musics.find({"id":{$ne:null}}).count();;
数据类型
ObjectId
_id
类型默认为ObjectId
。12 Byte格式:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
时间戳 | 主机 | PID | 计数器 |
推荐显式提供_id
,减轻数据库生成ID的负担。
数字类型
默认会把类型转为float
,所以整数要写明是NumberInt(0)
,
长整形要写明是NumberLong(0)
。
例:
db.data.update({'name': 'zero'}, {'$set': {'value': NumberInt(0)}})
日期
类型是Date
,创建时一定要调用new Date( ... )
来创建。用Date( ... )
创建出来的
是一个字符串而不是日期。
数组
{"favorite book" : ["cat's cradle", "foundation trilogy", "ender's game"]}
CRUD
- MongoDB默认CRUD操作都是异步的,也不关心返回结果。
-
为了保证操作成功,完成操作以后用
getLastError
命令检查。
插入
插入单个文档
db.foo.insert({"bar":"baz"})
- 单个文档最大大4MB(《战争与和平》也只有3.14MB)。
-
启动mongodb时用
--objectCheck
选项打开文档结构检查(会影响性能)。
批量插入
- 单个TCP请求插入多个文档到一个集合可节约重复的开销。
- 不能把多个文档批量插入到多个集合里。
-
如果目标是导入数据库,不应该用批量插入,而应该用
mongoimport
等工具。
删除
db.foo.remove({"opt-out":true})
如果要删除集合里所有的数据,直接删除集合比批量删除更加快。 但是要注意这样会把索引也一直删除。
更新文档:update
update
方法是原子性的,它有两个参数:
- 查询条件。
- 修改器(modifier)。
替换整个文档
如果要对一个文档做出比较大的修改,可以用$update
替换掉整个文档:
var joe = db.blog.findOne({"_id":ObjectId("53b426cd024df0e8f06f5921")}) joe.title = "Article 00"; db.blog.update({"_id":ObjectId("53b426cd024df0e8f06f5921")}, joe)
使用修改器修改文档的属性
修改器:set 更新属性的值
$set
用来指定一个key的值(如果没有就创建):
> db.blog.find(); { "_id" : ObjectId("53b55a9c35116a9ce3cc1933"), "title" : "Article 01" } // 创建新的key: > db.blog.update({"_id" : ObjectId("53b55a9c35116a9ce3cc1933")}, {"$set" : {"author.name" : "Jade"}}) // 改变key的值: > db.blog.update({"_id" : ObjectId("53b55a9c35116a9ce3cc1933")}, {"$set" : {"author.email" : "Jade@mailserver.com"}}) // key值的类型也可以改 > db.blog.update({"_id" : ObjectId("53b55a9c35116a9ce3cc1933")}, {"$set" : {"author.email" : [ "Jade@mailserver.com", "Adda@mailserver.com", "Teo@mailserver.com"]}})
修改器:unset去除属性
> db.blog.find(); { "_id" : ObjectId("53b55a9c35116a9ce3cc1933"), "title" : "Article 01", "author" : { "name" : "Jade", "email" : "Jade@mailserver.com" } } > db.blog.update({"_id" : ObjectId("53b55a9c35116a9ce3cc1933")}, {"$unset" : {"author.email" : ""}}) > db.blog.update({"_id" : ObjectId("53b55a9c35116a9ce3cc1933")}, {"$unset" : {"author.name" : ""}}) > db.blog.update({"_id" : ObjectId("53b55a9c35116a9ce3cc1933")}, {"$unset" : {"author" : ""}}) > db.blog.find(); { "_id" : ObjectId("53b55a9c35116a9ce3cc1933"), "title" : "Article 01" }
修改器:inc增加数字
原子增加操作,只作用于数字。也可以用来创建一个原来没有的属性。
> db.blog.update({"_id" : ObjectId("53b55a9c35116a9ce3cc1933")}, {"$inc" : {"score" : 1}}) > db.blog.find(); { "_id" : ObjectId("53b55a9c35116a9ce3cc1933"), "title" : "Article 01", "score" : 1 }
数组修改器:push添加一个元素
回到到尾部,如果没有会新建一个数组:
> db.blog.update({"_id" : ObjectId("53b55aa135116a9ce3cc1935")}, {$push : {"comments" : {"user" : "aa", "content" : "aaa"}}}) > db.blog.update({"_id" : ObjectId("53b55aa135116a9ce3cc1935")}, {$push : {"comments" : {"user" : "bb", "content" : "bbb"}}}) > db.blog.find() { "_id" : ObjectId("53b55aa135116a9ce3cc1935"), "title" : "Article 03", "comments" : [ { "user" : "aa", "content" : "aaa" }, { "user" : "bb", "content" : "bbb" } ] }
数组修改器:addToSet
$addToSet
在不重复的情况下添加:
> db.test.find() { "_id" : ObjectId("5617833823d1f1ede8d0f59c"), "user" : "jade", "books" : [ "book1", "book2", "book3" ] } > db.test.update({"user":"jade"},{"$addToSet": {"books":"book4"}}); > db.test.find() { "_id" : ObjectId("5617833823d1f1ede8d0f59c"), "user" : "jade", "books" : [ "book1", "book2", "book3", "book4" ] }
这样的操作相当于检查成员不存在(用$ne
检查),然后再添加:
> db.test.find(); { "_id" : ObjectId("5617833823d1f1ede8d0f59c"), "user" : "jade", "books" : [ "book1", "book2", "book3", "book4", "book5" ] } > db.test.update({"books": {"$ne": "book3"}}, {$push: {"books": "book3"}}); > db.test.find(); { "_id" : ObjectId("5617833823d1f1ede8d0f59c"), "user" : "jade", "books" : [ "book1", "book2", "book3", "book4", "book5" ] } > db.test.update({"books": {"$ne": "book6"}}, {$push: {"books": "book6"}}); > db.test.find(); { "_id" : ObjectId("5617833823d1f1ede8d0f59c"), "user" : "jade", "books" : [ "book1", "book2", "book3", "book4", "book5", "book6" ] }
\(addToSet
组合\)each
一次添加多个:
> db.test.update({"user":"jade"}, {"$addToSet": {"books": {"$each":["book1", "book3", "book5","book6"]}}}); > db.test.find() { "_id" : ObjectId("5617833823d1f1ede8d0f59c"), "user" : "jade", "books" : [ "book1", "book2", "book3", "book4", "book5", "book6" ] }
数组修改器:pop删除一个元素
-
{$pop : {key : 1}}
:从数组尾部删除一个元素。 -
{$pop : {key : -1}}
:从数组头部删除一个元素。
数组修改器:pull 按条件删除元素
$pull
可以根据条件来删除元素,而不是根据位置:
db.lists.insert({"todo":[1, 1, 2, 1]})
如果"$pull" : 1
,就只剩下2
了:
db.lists.update({}, {"$pull": 1})
数组定位修改器
数组下标从0
开始,可以用下标来选择元素:
> db.blob.posts.findOnd() { "_id" : ...... , "content" : .... , "comments" : [ { "comment" : "good post", "author" : "John", "votes" : 3 }, { "comment" : "good post", "author" : "Adda", "votes" : 2 }, { "comment" : "good post", "author" : "Freeman", "votes" : 1 } ] }
使用下标0
给第一个评论增加投票:
> db.blog.update({"post" : post_id}, {"$inc" : {"comments.0.votes" : 1}})
在不知道下标的时候,使用定位符$
匹配符合条件的记录。
比如修改用户名为John
的第一条评论:
> db.blog.update({"comments.author" : "John"}, {"$set" : {"comments.$.author" : "Jim}})
注意:定位符只会匹配查找到的第一条记录。
修改器的性能
对于某些不需要改变文档大小的修改器,运行速度是非常快的。例如:
from pymongo import Connection import time db = Connection().performace_test db.drop_collection("update") collection = db.update collection.insert({"x": 1}) # make shure insert is complete before timing collection.find_on3() start = time.time() for i in range(100000): collection.update({}, {"$inc": {"x": 1}}) # make sure the updates are complete before we stop timing collection.find_one() print time.time() - start
如果是push
这类会改变文档大小的操作,速度就差了很多:
for i in range(100000): collection.update({}, {"$push": {"x": 1}})
在很多场景下,\(push
还是合适的修改器,如果\)push
让性能成为瓶颈,
可以把内嵌的数组独立出来,作为一个新的集合。
更新或新增
upsert
update
函数可以通过第三个函数(true)来指定如果没有符合条件的,就创建新的文档。
这操作是原子性的:
> db.test.update({"user": "Neo"}, {"$inc": {"count": 3}}, true); WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : ObjectId("561a071212acab473f0bc93a") }) > db.test.find(); { "_id" : ObjectId("561a071212acab473f0bc93a"), "user" : "Neo", "count" : 3 }
save程序
save
是一个shell函数,当指定文档不存在时插入,如果已经存在就更新。
save
函数只有一个参数,就是文档。如果文档有_id
,执行upsert
,
否则就执行插入。
> var x = db.test.findOne(); > x.num = 42 > db.test.save(x) > db.test.find(); { "_id" : ObjectId("5617833823d1f1ede8d0f59c"), "user" : "jade", "books" : [ "book1", "book2", "book3", "book4", "book5", "book6" ], "num" : 42 }
更新多个文档
默认update
只更新第一个符合的记录,如果要更新所有匹配的文档,设置update
函数
的第4个参数为true
。
注意:
- 为了防止以后默认的行为变了默认更新多个,建议每次都指定第3第4个参数。
-
多文档更新只用用于
$
开关的修改器工具。
命令getlastError
可以用来查看空间更新了多少条记录,属性n
的值就是数量:
> db.test.update({"user": "Neo"}, {$inc: {"count": 2}}, false, true); > db.runCommand({getLastError: 1}); { "connectionId" : 1, "updatedExisting" : true, // 是对已有记录的修改 "n" : 3, // 更新了3条记录 "syncMillis" : 0, "writtenTo" : null, "err" : null, "ok" : 1 }
返回已经更新的文档:findAndModify
update
函数不管执行是否成功,而命令findAndModify
会等待数据库响应,
还具有原子性。
格式:
ps = db.runCommand({ "findAndModify" : "collName", // 集合名称,字符串类型 "query" : { ... }, // 查询条件 "sort" : { ... }, // 结果排序方式 "update" : { ... }, // 修改器 "new" : true/false, // 是否删除文档 "remove" : true/false // 返回的是新文档还是更新前的文档 })
例子:
有一个进程数据库processes
结构:
-
status
:状态,READY
、RUNNING
、DONE
。 -
priority
:优先级,数值型。
程序逻辑:
-
把所以
READY
的进程按优先级排序。 -
把最高优先级的更新为
RUNNING
,运行进程函数。 -
运行完以后,更新状态为
DONE
。
> db.processes.find(); { "_id" : ObjectId("561a1580d9352240db58ad03"), "status" : "READY", "priority" : 1 } { "_id" : ObjectId("561a1583d9352240db58ad04"), "status" : "READY", "priority" : 2 } { "_id" : ObjectId("561a1586d9352240db58ad05"), "status" : "READY", "priority" : 3 } { "_id" : ObjectId("561a1588d9352240db58ad06"), "status" : "READY", "priority" : 3 } { "_id" : ObjectId("561a158ad9352240db58ad07"), "status" : "READY", "priority" : 2 } { "_id" : ObjectId("561a1590d9352240db58ad08"), "status" : "READY", "priority" : 5 }
> var ps = db.runCommand({"findAndModify": "processes", ... "query": {"status": "READY"}, ... "sort" : {"priority": -1}, ... "update" : {"$set": {"status": "RUNNING"}}}).value > do_something(ps) // 执行进程任务 > db.process.update({"_id": ps._id}, {"$set": {"status": "DONE"}}); // 标记完成
查询
查询一条记录
> db.storeCollection.findOne({'version':'3.5'}) { "_id" : ObjectId("4ef970f23c1fc4613425accc"), "version" : "3.5", "segment" : "e3ol6" }
查询多条记录
db.foo.find({a : 1})
查看全部符合的数量:
db.foo.find({a : 1}).count()
条件运算符
-
$gt
:>
-
$lt
:<
-
$gte
:>=
-
$lte
:<=
-
$ne
:!=、<>
-
$in
:in
-
$nin
:not in
-
$all
:all
-
$not
: 反匹配(1.3.3及以上版本)
查询 name <> "bruce" and age >= 18 的数据 db.users.find({name: {$ne: "bruce"}, age: {$gte: 18}}); 查询 creation_date > '2010-01-01' and creation_date <= '2010-12-31' 的数据 db.users.find({creation_date:{$gt:new Date(2010,0,1), $lte:new Date(2010,11,31)}); 查询 age in (20,22,24,26) 的数据 db.users.find({age: {$in: [20,22,24,26]}}); 查询 age取模10等于0 的数据 db.users.find('this.age % 10 == 0'); 或者 db.users.find({age : {$mod : [10, 0]}}); 匹配所有 db.users.find({favorite_number : {$all : [6, 8]}}); 可以查询出{name: 'David', age: 26, favorite_number: [ 6, 8, 9 ] } 可以不查询出{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] } 查询不匹配name=B*带头的记录 db.users.find({name: {$not: /^B.*/}}); 查询 age取模10不等于0 的数据 db.users.find({age : {$not: {$mod : [10, 0]}}}); #返回部分字段 选择返回age和_id字段(_id字段总是会被返回) db.users.find({}, {age:1}); db.users.find({}, {age:3}); db.users.find({}, {age:true}); db.users.find({ name : "bruce" }, {age:1}); 0为false, 非0为true 选择返回age、address和_id字段 db.users.find({ name : "bruce" }, {age:1, address:1}); 排除返回age、address和_id字段 db.users.find({}, {age:0, address:false}); db.users.find({ name : "bruce" }, {age:0, address:false}); 数组元素个数判断 对于{name: 'David', age: 26, favorite_number: [ 6, 7, 9 ] }记录 匹配db.users.find({favorite_number: {$size: 3}}); 不匹配db.users.find({favorite_number: {$size: 2}}); $exists判断字段是否存在 查询所有存在name字段的记录 db.users.find({name: {$exists: true}}); 查询所有不存在phone字段的记录 db.users.find({phone: {$exists: false}}); $type判断字段类型 查询所有name字段是字符类型的 db.users.find({name: {$type: 2}}); 查询所有age字段是整型的 db.users.find({age: {$type: 16}}); 对于字符字段,可以使用正则表达式 查询以字母b或者B带头的所有记录 db.users.find({name: /^b.*/i}); $elemMatch(1.3.1及以上版本) 为数组的字段中匹配其中某个元素 Javascript查询和$where查询 查询 age > 18 的记录,以下查询都一样 db.users.find({age: {$gt: 18}}); db.users.find({$where: "this.age > 18"}); db.users.find("this.age > 18"); f = function() {return this.age > 18} db.users.find(f); 排序sort() 以年龄升序asc db.users.find().sort({age: 1}); 以年龄降序desc db.users.find().sort({age: -1}); 限制返回记录数量limit() 返回5条记录 db.users.find().limit(5); 返回3条记录并打印信息 db.users.find().limit(3).forEach(function(user) {print('my age is ' + user.age)}); 结果 my age is 18 my age is 19 my age is 20 限制返回记录的开始点skip() 从第3条记录开始,返回5条记录(limit 3, 5) db.users.find().skip(3).limit(5); 查询记录条数count() db.users.find().count(); db.users.find({age:18}).count(); 以下返回的不是5,而是user表中所有的记录数量 db.users.find().skip(10).limit(5).count(); 如果要返回限制之后的记录数量,要使用count(true)或者count(非0) db.users.find().skip(10).limit(5).count(true); 分组group() 假设test表只有以下一条数据 { domain: "www.mongodb.org" , invoked_at: {d:"2009-11-03", t:"17:14:05"} , response_time: 0.05 , http_action: "GET /display/DOCS/Aggregation" } 使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count; db.test.group( { cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}} , key: {http_action: true} , initial: {count: 0, total_time:0} , reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time } , finalize: function(out){ out.avg_time = out.total_time / out.count } } ); [ { "http_action" : "GET /display/DOCS/Aggregation", "count" : 1, "total_time" : 0.05, "avg_time" : 0.05 } ]
索引
查看索引
db.system.indexes.find()
创建索引
格式:
ensureIndex(keypattern [, options])
例子:
db.page.ensureIndex({'title':1, 'url':-1})
查询索引
db.page.getIndexes()
删除索引
两种方法:
db.mycoll.dropIndex(name)
db.mycoll.dropIndexes()
索引重建
db.page.reIndex()