基础
原理
Mongodb 并发控制之乐观锁
Mongodb不善于处理事务,但提供了findAndModify命令。该命令允许对文档进行原子性更新,并在同一次调用中返回:
db.collection_yown.findAndModify( { query:{"name":"yown"},update:{"version":2},new:true or false } )
findAndModify是有返回值的,输出中的value字段即返回修改之前的文档,使用 new:true选项返回修改后的文档。
update是更新操作,是没有返回值的。
findAndModify 强调操作的原子性(atomically),比如用来实现自增1的操作或者操作队列。属于 get-and-set 式的操作,一般来讲,findAndModify 比update操作稍慢,因为需要等待数据库的响应。
另外findAndModify ,其中modify可以是update,还可以是remove
findAndModify可能引起的原子性问题
update 方法的三个参数是upsert,这个参数是个布尔类型,默认是false。当它为true的时候,update方法会首先查找与第一个参数匹配的记录,在用第二个参数更新之,如果找不到与第一个参数匹配的的记录,就插入一条
当findAndModify()包含upsert:true选项,并且查询字段不是唯一索引时,该方法可能会在某些情况下多次插入文档。
如下:
db.people.findAndModify({ query: { name: "Andy" }, sort: { rating: 1 }, update: { $inc: { score: 1 } }, upsert: true })
当多个客户端同时发出了这个指令,然后在服务端并行执行,而都没有找到query的匹配,可能同时执行了多个upsert操作。导致数据重复。
如果不使用upsert,就没有这种问题。
使用$isolation来保证隔离性
使用$isolated操作符可以保证单个写入操作修改多个文档的时候不被交错。
$isolated其实是在整个数据库(Mongodb的手册对这点说明不清楚,也可能是在集合层面加独占锁,但是有一点文档中是说明的,不论在哪个层面加独占锁,都会导致真个数据库单线程化)加独占锁(即使是对于WiredTiger存储引擎也是),在这期间不能进行其他任何的读写操作。所以如果$isolated的操作执行的时间过长,会大大的影响系统的并发性能。
db.foo.update( { status : "A" , $isolated : 1 }, { $inc : { count : 1 } }, { multi: true } ) $ isolation不保证多个文档操作的原子性。 $ isolation保证多个文档操作不会被跟其他操作交错。 $ isolation保证此操作在进行到某一个文档的更新的时候,在不提交或者回滚之前,不会被客户端看到。也就是说不会导致这个文档的查询产生脏读。
对比MySQL,你究竟在什么时候更需要MongoDB(转载)
优点:
更高的写负载
MongoDB更关注高的插入速度不可靠环境保证高可用性
设置副本集(主-从服务器设置)不仅方便而且很快,此外,使用MongoDB还可以快速、安全及自动化的实现节点(或数据中心)故障转移未来会有一个很大的规模
数据库扩展是非常有挑战性的,当单表格大小达到5-10GB时,MySQL表格性能会毫无疑问的降低。如果你需要分片并且分割你的数据库,MongoDB将很容易实现这一点。容易扩展,可以支持T级别的数据量。
使用基于位置的数据查询
MongoDB支持二维空间索引,因此可以快速及精确的从指定位置获取数据。(唯一索引 复合索引)
非结构化数据的爆发增长
鉴于MongoDB的弱数据结构模式,添加1个新字段不会对旧表格有任何影响,整个过程会非常快速2000-3000以上读写每秒
数据模型不用确定
大量地理位置查询
不足:
必须避免在要求高事务安全的情景下使用MongoDB
比如一个1000万美元的交易Mongodb在保存数据的时候,不是实时写入到硬盘的,所以有可能出现数据丢失的情况
多表关联仅仅支持Left Outer Join
16MB文档大小限制
不支持中文排序
MongoDB中的一些坑
数据库级锁
建索引导致数据库阻塞
建索引就是一个容易引起长时间写锁的问题,MongoDB 在前台建索引时需要占用一个写锁(而且不会临时放弃),如果集合的数据量很大,建索引通常要花比较长时间,特别容易引起问题
解决的方法很简单,MongoDB 提供了两种建索引的访问,一种是 background 方式,不需要长时间占用写锁,另一种是非 background 方式,需要长时间占用锁。使用 background 方式就可以解决问题。
db.posts.ensureIndex({user_id: 1}, {background: 1})
不合理使用嵌入 embed document
解决问题的方法,就是把 embed 关联更改成的普通外键关联,就是类似关系数据库的做法
当关联对象的数据不固定或者经常发生变化时,一定要避免使用 embed 关联,不然会死的很惨。
不合理使用 Array 字段
频繁的增加修改操作导致大量长时间数据库写锁,从而引发 MongoDB 数据库性能急剧下降
解决问题的方法:
我们把Array转移到了内存数据库 redis 中,避免了频繁更改 MongoDB 中的 User, 从而彻底解决问题。 如果不使用 redis,也可以建立一个锁集合,使用外键形式关联。
MongoDb安装
安装
wget --no-check-certificate http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.6.tgz tar -zxvf mongodb-linux-x86_64-3.0.6.tgz
yum安装
增加repo库配置文件
/etc/yum.repos.d/mongodb-org-3.2.repo
内容为
1 | [mongodb-org-3.2] |
安装
yum install -y mongodb-org
启动
service mongod restart
mongod -f /etc/mongod.conf #如果没有正常关闭数据库,则用这个命令启动
Cent OS 7上需要把mongoDB添加到systemd,否则会出现下面的错误
systemd[1]: Failed to start SYSV: Mongo is a scalable, document-oriented database..
# vi /usr/lib/systemd/system/mongod.service
[Unit]
Description=mongodb database
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=--quiet -f /etc/mongod.conf"
ExecStart=/usr/bin/mongod $OPTIONS run
PIDFile=/var/run/mongodb/mongod.pid
[Install]
WantedBy=multi-user.target
建立链接
# ln -s /usr/lib/systemd/system/mongod.service /etc/systemd/system/multi-user.target.wants/
重新加载systemctl
# systemctl daemon-reload
配置/etc/mongod.conf
两款Mongodb的可视化工具,支持最新的Mongodb 3.2版本。
MongoBooster
下载地址:http://mongobooster.com/downloads
MongoChef
个人免费,用于商业需要有授权
下载地址:http://3t.io/mongochef/download/platform/
操作
- db.help()
查看命令提示
- show dbs
显示数据库,需要注意的是show dbs,只会显示有数据的库,没有数据的库,是不会显示的。
根据时间查询
在FIND里面($gte/$lte/$gt/$lt)
{ "startTime": { $gte:"2015/07/12" } } { "_id" : ObjectId("561b2fb705924b08dc94ff8a") }
更新列名
在UPDATE里面
{$rename : {"groupName" : "group_name"}}
删除列
在UPDATE里面
{$unset:{"id":10}}
批量更新内容
db.rank_scores.find({}).forEach(
function(item){
if(item.userName.indexOf("player_")>=0)
db.rank_scores.update({"_id":item._id},{$set:{"userName":"user_"+item.userName.substr(7)}},false,true)
}
)
连接本机
./mongo --port 37017
报错:child process failed, exited with error number 100
没有正常关闭mongodb引起的。
先删除/home/cxy/mongodb/interstellar/db/下的mongod.lock
然后以repair的模式启动
./mongod --config ../conf/interstellar.conf --repair
然后接着在启动一次
./mongod --config ../conf/interstellar.conf
现在就可以查看到mongod的进程存在了,可以正常使用了
如何正常关闭mongodb?
先通过shell连上服务器:
mongo use admin db.shutdownServer()
创建用户
use admin db.createUser( { user: "root", pwd: "_gamedo188", roles: [ "root" ] } ) db.createUser( { user: "sa", pwd: "_gamedo188", roles: [ { role: "__system", db: "admin" } ] } )
登录用户
db.auth("sa", "_gamedo188")
安全验证启动
./mongod --auth --config ../interstellar.conf
查看mongodb最大连接数
db.serverStatus().connections
查看一个表wechatkeys的索引
db.getCollection('wechatkeys').getIndexes()
新建一个表wechatkeys的索引key,1为升序,2为降序
db.getCollection('wechatkeys').ensureIndex({key:1})
绑定数据库到指定内网ip,防止外网访问攻击
bind_ip=127.0.0.1
返回部分字段
举例:
1 | 1. 返回name和age两个字段(默认会返回_id) |
- $exists 当前不能使用索引,但 $ne 可以
1 | db.players.count({fb:{$ne:null}}) |
备份mongo
备份
./mongodump -d critz -o /www/backups/mongodb/critz-2016-02-18
mongodump有一个值得一提的选项是–oplog
==mongodump的进行过程中并不会把数据库锁死以保证整个库冻结在一个固定的时间点,这在业务上常常是不允许的。==
所以就有了dump的最终结果中A集合是10点整的状态,而B集合则是10点零1分的状态这种情况。这样的备份即使恢复回去,可以想象得到的结果恐怕意义有限。那么上面这个oplog.bson的意义就在这里体现出来了。如果在dump数据的基础上,再重做一遍oplog中记录的所有操作,这时的数据就可以代表dump结束时那个时间点(point-in-time)的数据库状态。
压缩
cd /www/backups/mongodb tar zcvf critz-2016-02-18.tar.gz critz-2016-02-18 cp critz-2016-02-18.tar.gz /www/dotado/jetty-8888/webapps/ROOT/
恢复
./mongorestore -d critz /www/mongodb/backups/critz-2016-03-30/critz
shell备份脚本
#!/bin/sh # mogodb mogodbdirname="interstellar-`date +%y-%m-%d`" mogodbfilename="`date +%y-%m-%d`.tar.gz" cd /www/mongodb/mongodb-linux-x86_64-3.0.6/bin/ ./mongodump -d interstellar -o /www/backups/mongodb/$mogodbdirname cd /www/backups/mongodb tar zcvf $mogodbfilename $mogodbdirname
实战
实用技巧
sort排序动态字段
定义排序变量,然后使用即可
1 | var sortOp = {}; |
- MongoDB 实现按列累加统计
1 | // 统计总共积分是多少 |
- 统计最高最低平均
1 | db.actives5.aggregate([{$group:{_id: null,maxScore: { $max: '$score' },minScore: { $min: '$score' },avgScore: { $avg: '$score' }}}]) |
- 导出导入单独表
1 | mongoexport -d xxxxxx -o actives.json -c actives |
- 建立索引
1 | db.players.ensureIndex({fb:1}) |
- 模糊查询
1 | const reg = new RegExp(data.search, 'i'); //不区分大小写 |
- 查看db状态
1 | # mongostat |
- 查看mongodb的日志
1 | # tail -n500 -f /var/log/mongodb/mongod.log |
- mongodb的快速迁移
1 | mongodb数据库的迁移除了常规的mongodump、mongoexport、mongorestore、mongoimport之外,可以采用直接拷贝数据库文件的方式进行。 |
- 查询数据导出
- 新建一个js文件,将查询方法写进去,如playersPage_1_1.js,文件内容如下
1 | var c = db.playersPage.aggregate([{ $match: {date:{$lt:"2018-09-15"}}},{"$group" : {_id:{lp1:"$lp1"}, count:{$sum:1}}}]); |
- 输入命令来执行
1 | mongo localhost:27017/ludosocket playersPage_1_1.js > playersPage_1_1.2018-09-17.csv |
这样查询的结果就会直接生成在当前文件夹下的playersPage_1_1.2018-09-17.js文件
- group by count 分组count
如:查询日期小于2018-09-15,根据lp1分组的玩家总数
1 | db.playersPage.aggregate([{ $match: {date:{$lt:"2018-09-15"}}},{"$group" : {_id:{lp1:"$lp1"}, count:{$sum:1}}}]) |
如:查询日期小于2018-09-15,根据lp1和lp2组合分组的玩家总数
1 | db.playersPage.aggregate([{ $match: {date:{$lt:"2018-09-15"}}},{"$group" : {_id:{lp1:"$lp1",lp2:"$lp2"}, count:{$sum:1}}}]) |
数据库高可用和分区解决方案-MongoDB 篇
http://udn.yyuap.com/article-8203.html
MongoDB Sharding 集群配置
Sharding cluster介绍
这是一种可以水平扩展的模式,在数据量很大时特给力,实际大规模应用一般会采用这种架构去构建monodb系统。
MongoDB Sharding技术的应用场景:
A.如果数据集data set大小将要或者已经超过了单个MongoDB实例的容量大小。 B.活动的工作集working set大小将要超过最大物理内存大小 C.单个MongoDB实例无法满足频繁的写操作。
如果以上三种情况没有满足,不需要部署sharding,只会增加复制度,同时在设计数据模型时,也要考虑到以后作分片的情况。
Sharding只会在数据量比较大的情况下才会发挥作用,默认的chunk大小是64MB,只有在满足特定条件下,balancer进程才会将数据迁移到其他shard上,否则数据会一直存储到单个shard上。
主要是从几个方面考虑这个问题:
1、方便扩展,如果需要横向扩展,把shardkey加上,然后加资源即可。 2、避免不同的程序驱动对rs高可用的不一致情况。 3、虚拟化后config的资源消耗主要是磁盘io,其他cpu、内存、磁盘容量等都几乎可以忽略不计。 4、统一资源形式,如果同时既提供rs也提供shard的话,对MongoDB不怎么熟悉的用户其实是很容易混淆。
要构建一个 MongoDB Sharding Cluster,需要三种角色:
Shard Server: mongod 实例,用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个relica set承担,防止主机单点故障 Config Server: mongod 实例,存储了整个 Cluster Metadata,其中包括 chunk 信息。 Route Server: mongos 实例,前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。用于分摊客户端的请求压力。如果使用多个mongos实例,可以使用HAProxy或者LVS等代理来转发客户端请求到后端的mongos,必须要配置成client affinity模式保证来自同一个客户端的请求转发到后端相同的mongos.通常会将mongos实例部署到应用服务器上
实际环境架构
分别在3台机器运行一个mongod实例(称为mongod shard11,mongod shard12,mongod shard13)组织replica set1,作为cluster的shard1 分别在3台机器运行一个mongod实例(称为mongod shard21,mongod shard22,mongod shard23)组织replica set2,作为cluster的shard2 每台机器运行一个mongod实例,作为3个config server 每台机器运行一个mongos进程,用于客户端连接
主机 | IP | 端口信息 |
Server1 | 10.1.1.1 | mongod shard11:27017 mongod shard12:27018 mongod config1:20000 mongs1:30000 |
Server2 | 10.1.1.2 | mongod shard12:27017 mongod shard22:27018 mongod config2:20000 mongs2:30000 |
Server3 | 10.1.1.3 | mongod shard13:27017 mongod shard23:27018 mongod config3:20000 mongs3:30000 |
软件准备
创建用户
groupadd -g 20001 mongodb useradd -u 20001 -g mongodb mongodb passwd mongodb
安装monodb软件
su – mongodb tar zxvf mongodb-linux-x86_64-1.6.2.tar
安装好后,目录结构如下:
tree mongodb-linux-x86_64-1.6.2 mongodb-linux-x86_64-1.6.2 |– GNU-AGPL-3.0 |– README |– THIRD-PARTY-NOTICES `– bin |– bsondump |– mongo |– mongod |– mongodump |– mongoexport |– mongofiles |– mongoimport |– mongorestore |– mongos |– mongosniff `– mongostat
创建数据目录
根据本例sharding架构图所示,在各台sever上创建shard数据文件目录
Server1: su – monodb cd /home/monodb mkdir -p data/shard11 mkdir -p data/shard21 Server2: su – monodb cd /home/monodb mkdir -p data/shard12 mkdir -p data/shard22 Server3: su – monodb cd /home/monodb mkdir -p data/shard13 mkdir -p data/shard23
配置replica sets
配置shard1所用到的replica sets:
Server1:
cd /home/mongodb/mongodb-linux-x86_64-1.6.2/bin ./mongod –shardsvr –replSet shard1 –port 27017 –dbpath /home/mongodb/data/shard11 –oplogSize 100 –logpath /home/mongodb/data/shard11.log –logappend –fork
Server2:
cd /home/mongodb/mongodb-linux-x86_64-1.6.2/bin ./mongod –shardsvr –replSet shard1 –port 27017 –dbpath /home/mongodb/data/shard12 –oplogSize 100 –logpath /home/mongodb/data/shard12.log –logappend –fork
Server3:
cd /home/mongodb/mongodb-linux-x86_64-1.6.2/bin ./mongod –shardsvr –replSet shard1 –port 27017 –dbpath /home/mongodb/data/shard13 –oplogSize 100 –logpath /home/mongodb/data/shard13.log –logappend –fork
初始化replica set
用mongo连接其中一个mongod,执行:
config = {_id: ‘shard1′, members: [ {_id: 0, host: '10.1.1.1:27017'}, {_id: 1, host: '10.1.1.2:27017'}, {_id: 2, host: '10.1.1.3:27017'}] } rs.initiate(config);
同样方法,配置shard2用到的replica sets:
server1:
cd /home/mongodb/mongodb-linux-x86_64-1.6.2/bin
./mongod –shardsvr –replSet shard2 –port 27018 –dbpath /home/mongodb/data/shard21 –oplogSize 100 –logpath /home/mongodb/data/shard21.log –logappend –fork
server2:
cd /home/mongodb/mongodb-linux-x86_64-1.6.2/bin
./mongod –shardsvr –replSet shard2 –port 27018 –dbpath /home/mongodb/data/shard22 –oplogSize 100 –logpath /home/mongodb/data/shard22.log –logappend –fork
server3:
cd /home/mongodb/mongodb-linux-x86_64-1.6.2/bin
./mongod –shardsvr –replSet shard2 –port 27018 –dbpath /home/mongodb/data/shard23 –oplogSize 100 –logpath /home/mongodb/data/shard23.log –logappend –fork
初始化replica set
用mongo连接其中一个mongod,执行:
config = {_id: ‘shard2′, members: [
{_id: 0, host: '10.1.1.1:27018'},
{_id: 1, host: '10.1.1.2:27018'},
{_id: 2, host: '10.1.1.3:27018'}]
}
rs.initiate(config);
配置三台config server
Server1:
mkdir -p /home/mongodb/data/config ./mongod –configsvr –dbpath /home/mongodb/data/config –port 20000 –logpath /home/mongodb/data/config.log –logappend –fork #config server也需要dbpath
Server2:
mkdir -p /home/mongodb/data/config ./mongod –configsvr –dbpath /home/mongodb/data/config –port 20000 –logpath /home/mongodb/data/config.log –logappend –fork
Server3:
mkdir -p /home/mongodb/data/config ./mongod –configsvr –dbpath /home/mongodb/data/config –port 20000 –logpath /home/mongodb/data/config.log –logappend –fork
配置mongos实例(query routers)
在server1,server2,server3上分别执行:
./mongos –configdb 10.1.1.1:20000,10.1.1.2:20000,10.1.1.3:20000 –port 30000 –chunkSize 5 –logpath /home/mongodb/data/mongos.log –logappend –fork
mongs不需要dbpath
Configuring the Shard Cluster
连接到其中一个mongos进程,并切换到admin数据库做以下配置
连接到mongs,并切换到admin
./mongo 10.1.1.1:30000/admin db Admin
加入shards
如果shard是单台服务器,用db.runCommand( { addshard : “
[: ]” } )这样的命令加入,如果shard是replica sets,用replicaSetName/ [:port][,serverhostname2[:port],…]这样的格式表示,例如本例执行: db.runCommand( { addshard : "shard1/10.1.1.1:27017,10.1.1.2:27017,10.1.1.3:27017″,name:"s1″,maxsize:20480} ); db.runCommand( { addshard : "shard2/10.1.1.1:27018,10.1.1.2:27018,10.1.1.3:27018″,name:"s2″,maxsize:20480} );
注意:在添加第二个shard时,出现error:test database 已经存在的错误,这里用mongo命令连接到第二个replica set,用db.dropDatabase()命令把test数据库给删除然后就可加入
可选参数
Name:用于指定每个shard的名字,不指定的话系统将自动分配 maxSize:指定各个shard可使用的最大磁盘空间,单位megabytes
Listing shards
db.runCommand( { listshards : 1 } )
如果列出了以上二个你加的shards,表示shards已经配置成功
激活数据库分片
命令:
db.runCommand( { enablesharding : "<dbname>" } );
通过执行以上命令,可以让数据库跨shard,如果不执行这步,数据库只会存放在一个shard,一旦激活数据库分片,数据库中不同的collection将被存放在不同的shard上,但一个collection仍旧存放在同一个shard上,要使单个collection也分片,还需单独对collection作些操作
Collecton分片
要使单个collection也分片存储,需要给collection指定一个分片key,通过以下命令操作:
db.runCommand( { shardcollection : "<namespace>",key : <shardkeypatternobject> }); 注: a. 分片的collection系统会自动创建一个索引(也可用户提前创建好) b. 分片的collection只能有一个在分片key上的唯一索引,其它唯一索引不被允许 One note: a sharded collection can have only one unique index, which must exist on the shard key. No other unique indexes can exist on the collection.
分片collection例子
db.runCommand( { shardcollection : "test.c1″,key : {id: 1} } ) for (var i = 1; i <= 200003; i++) db.c1.save({id:i,value1:"1234567890″,value2:"1234567890″,value3:"1234567890″,value4:"1234567890″}); db.c1.stats() { “sharded” : true, “ns” : “test.c1″, “count” : 200003, “size” : 25600384, “avgObjSize” : 128, “storageSize” : 44509696, “nindexes” : 2, “nchunks” : 15, “shards” : { “s1″ : { “ns” : “test.c1″, “count” : 141941, “size” : 18168448, “avgObjSize” : 128, “storageSize” : 33327616, “numExtents” : 8, “nindexes” : 2, “lastExtentSize” : 12079360, “paddingFactor” : 1, “flags” : 1, “totalIndexSize” : 11157504, “indexSizes” : { “_id_” : 5898240, “id_1″ : 5259264 }, “ok” : 1 }, “s2″ : { “ns” : “test.c1″, “count” : 58062, “size” : 7431936, “avgObjSize” : 128, “storageSize” : 11182080, “numExtents” : 6, “nindexes” : 2, “lastExtentSize” : 8388608, “paddingFactor” : 1, “flags” : 1, “totalIndexSize” : 4579328, “indexSizes” : { “_id_” : 2416640, “id_1″ : 2162688 }, “ok” : 1 } }, “ok” : 1 }
问题汇总
Mongodb 占用99%CPU并且查询速度很慢原因查找
因为程序有将近40个线程一直在不停的查询数据库并插入, 而竟然没有在数据库中建索引
建立索引后CPU使用率瞬间降下来了,并且速度超快,抽查也顺利起来了
分析数据库正在执行的请求
执行 db.currentOp() 命令,能看到数据库当前正在执行的操作
secs_running/microsecs_running: 这个值重点关注,代表请求运行的时间,如果这个值特别大,就得注意了,看看请求是否合理
- DeprecationWarning: Mongoose: mpromise (mongoose’s default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
建立连接前增加这句即可
1 | mongoose.Promise = global.Promise; // ADD THIS |
- WiredTiger引起的Cannot allocate memory问题
问题日志:
1 | 2018-08-28T13:59:02.505+0000 E STORAGE [conn6943] WiredTiger (12) [1535464742:504284][15309:0x7fc22c103700], file:collection-4--4936006946892585673.wt, WT_CURSOR.insert: memory allocation of 17522688 bytes failed: Cannot allocate memory |
解决办法:
1 | 配置文件里加入了 cacheSizeGB: 3 |
查看WiredTiger内部缓存到底占用了多少内存的方式是,在mongo shell中之行以下命令
1 | db.runCommand( { serverStatus: 1 } ).wiredTiger.cache["bytes currently in the cache"] |
如果不想重启mongoDB,可以在线修改,如下
1 | db.adminCommand({setParameter: 1, wiredTigerEngineRuntimeConfig: "cache_size=8G"}) |
Mongoose
Node.js Mongoose 参考手册
Mongoose就是一套操作MongoDB数据库的接口
Schema
数据属性模型(传统意义的表结构)
1 | var TestSchema = new mongoose.Schema({ |
Model
具有数据库操作的行为,类似于管理数据库属性、行为的类
1 | var db = mongoose.connect("mongodb://127.0.0.1:27017/test"); |
Entity
由Model创建的实体,使用save方法保存数据
1 | var TestEntity = new TestModel({ |
ObjectId
默认的主键_id
ObjectId是一个12字节的 BSON 类型字符串。按照字节顺序,依次代表:
1 | 4字节:UNIX时间戳 |
- Model 文档操作
- 查询
1 | model.find({}, callback); |
条件查询:
1 | “$lt” 小于 |
或查询 OR:
1 | ‘$in’ 一个键对应多个值 |
类型查询:
1 | null 能匹配自身和不存在的值, 想要匹配键的值 为null, 就要通过 “$exists” 条件判定键值已经存在 |
正则表达式:
MongoDb 使用 Prel兼容的正则表达式库来匹配正则表达式
1 | find( {“name” : /joe/i } ) |
查询数组:
1 | Model.find({“array”:10} ); |
where
用它可以执行任意javacript语句作为查询的一部分,如果回调函数返回 true 文档就作为结果的一部分返回
1 | find( |
简化版本
1 | find( {"$where" : "this.x + this.y === 10" } ) |
游标:
1 | limit(3) 限制返回结果的数量, |
- 创建, 在集合中创建一个文档
1 | Model.create(文档数据, callback)) |
- 更新,参数1:查询条件, 参数2:更新对象,可以使用MondoDB的更新修改器
1 | Model.update(conditions, update, function(error) |
更新修改器:
1 | ‘$inc’ 增减修改器,只对数字有效.下面的实例: 找到 age=22的文档,修改文档的age值自增1 |
数组修改器:
1 | ‘$push’ 给一个键push一个数组成员,键不存在会创建 |
- 删除, 参数1:查询条件
1 | Model.remove(conditions,callback); |
- Entity 文档操作
构造函数, 其实就是model的实例
1 | new TestModel( { name:‘xueyou’, age:21 } ); |
创建, 在集合中创建一个文档.
1 | Entity.save(callback); |
实战
千万数据维护
- 后台索引
- 索引创建方式
https://blog.csdn.net/wll_1017/article/details/78029273
1 | 前台方式 |
- 查看索引创建进度
1 | db.currentOp( |
结果如下:
1 | { |
==经估算:9275912条数据大概要50小时完成索引的建立==
- 终止索引的创建
1 | db.killOp(opid) // opid为上面操作的参数opid值 |
- 索引创建期间注意事项
1 | 如前所述,基于后台创建索引时,其他的数据库操作能被完成。但是对于mongo shell会话或者你正在创建索引的这个连接 |
- 索引创建期间性能
1 | 后台创建索引比前台慢,如果索引大于实际可用内存,则需要更长的时间来完成索引创建 |
- 随机数更新字段内容
把name字段内容为Guest的改成Guest+4位随机数1
2
3
4
5db.robots.find({name:"Guest"}).forEach(
function(item){
db.robots.update({"_id":item._id},{$set:{name:"Guest" + Math.floor(Math.random() * 10000 + 10000)%10000}})
}
)
问题汇总
- 频繁保存更新Mix字段的被覆盖问题
a