位置: 编程技术 - 正文
推荐整理分享MongoDB使用小结 一些常用操作分享(mongodb使用场景总结),希望有所帮助,仅作参考,欢迎阅读内容。
文章相关热门搜索词:mongodb使用方法,mongodb基本使用,mongodb基本操作,mongodb使用方法,mongodb使用方法,mongodb基本操作,mongodb使用场景 简书,mongodb使用方法,内容如对您有帮助,希望把文章链接给更多的朋友!
MongoDB的使用之前也分享过一篇,稍微高阶点:见这里:《MongoDB使用小结》
1、shell登陆和显示
假设在本机上有一个端口为的MongoDB服务,假设已经把mongo bin文件加入到系统PATH下。
登陆:mongo --port
显示DB:show dbs
进入某DB:use test_cswuyg
显示集合:show tables
2、简单查找查找文档:db.test_mac_id.find({'a': 'b'})
删除文档:db.test_mac_id.remove({'a': 'b'})
查找找到某一天的数据:
db.a.find({'D' : ISODate('--T::Z')}) 或者 db.a.find({'D' : ISODate('--')})
删除某一天的数据:
db.region_mac_id_result.remove({"D" : ISODate('--')})
小于.6.5的数据:
db.xxx.find({E: {$lt :ISODate('--')}})
大于等于.6.1的数据:
db.xxx.find({E: {$gte: ISODate("--")}}).count()
两个条件:
db.xxx.find({E:{$gte: ISODate("--"), $lte: ISODate("--")}}).count()
json中的嵌套对象查询,采用“点”的方式:
mongos> db.wyg.find({"a.b": {$exists: true}})
{ "_id" : "c", "a" : { "b" : } }
某个字段存在,且小于有多少:
db.stat.find({_: ISODate("--"), "": {$exists: 1, $lte: }}, {"": 1}).count()
3、存在和遍历统计存在'i': 1,且存在old_id字段:
mongos> var it = db.test.find({'i': 1, "old_id": {$exists: 1}})
遍历计数1:mongos> var count = 0;while(it.hasNext()){if (it.next()["X"].length==)++count}print(count)
遍历计数2:mongos> var count = 0;while(it.hasNext()){var item = it.next(); if (item['X'].length== && item['_id'] != item['X'])++count;if(!item['X'])++count;}print(count)
4、插入和更新> db.test.findOne({_id: 'cswuyg'})
null
> db.test.insert({'_id': 'cswuyg', 'super_admin': true})
> db.test.findOne({'_id': 'cswuyg'})
{
"_id" : "cswuyg",
"super_admin" : true
}
db.test.update({'_id': 'cswuyg'}, {$set: {'super_admin': true}})
5、repair 操作对某个DB执行repair:进入要repair的db,执行db.repairDatabase()
对mongodb整个实例执行repair:numactl --interleave=all /mongod --repair --dbpath=/home/disk1/mongodata/shard/
6、mongodb任务操作停止某个操作:
批量停止:
db.currentOp().inprog.forEach(function(item){db.killOp(item.opid)})当查询超过秒的,停止:
db.currentOp().inprog.forEach(function(item){if(item.secs_running > )db.killOp(item.opid)})停止某个数据源的查询:
db.currentOp().inprog.forEach(function(item){if(item.ns == "cswuyg.cswuyg")db.killOp(item.opid)})把所有在等待锁的操作显示出来:
db.currentOp().inprog.forEach(function(item){if(item.waitingForLock)print(JSON.stringify(item))})把处于等待中的分片显示出来:
db.currentOp().inprog.forEach(function(item){if(item.waitingForLock){print(item.opid.substr(0,9));print(item.op);}})把非等待的分片显示出来:
db.currentOp().inprog.forEach(function(item){if(!item.waitingForLock){var lock_info = item["opid"];print(lock_info.substr(0,9));print(item["op"]);}})查找所有的查询任务:
db.currentOp().inprog.forEach(function(item){if(item.op=="query"){print(item.opid);}})查找所有的非查询任务:
db.currentOp().inprog.forEach(function(item){if(item.op!="query"){print(item.opid);}})查找所有的操作:
db.currentOp().inprog.forEach(function(item){print(item.op, item.opid);});常用js脚本,可直接复制到mongo-shell下使用:
显示当前所有的任务状态:
杀掉某些特定任务:
(1)
db.currentOp().inprog.forEach(function(item){if(item.waitingForLock){var lock_info = item["opid"];if(item.op=="query" && item.secs_running > && item.ns=="cswuyg.cswuyg"){db.killOp(item.opid)}}})(2)
7、删除并返回数据old_item = db.swuyg.findAndModify({query: {"_id": "aabbccdd"}, fields:{"D": 1,'E':1, 'F':1}, remove: true})
fields里面为1的是要返回的数据。
8、分布式集群部署情况(1) 细致到collection的显示:sh.status()
(2)仅显示分片:
use config; db.shards.find()
{ "_id" : "shard", "host" : "xxhost:" }
{ "_id" : "shard", "host" : "yyhost:" }
....
(3)
use admin
db.runCommand({listshards: 1})
列出所有的shard server
9、正则表达式查找正则表达式查询:mongos> db.a.find({"tt": /t*/i}){ "_id" : ObjectId("be0fcbdefb"), "aa" : "1", "tt" : "tt" }其中i表明是否是case-insensitive,有i则表示忽略大小写
db.testing.find({"name":/[7-9]/})
当name的值为这几个数字组成的字符串时,查询命中。
、查询性能db.testing.find({name: }).explain()
输出结果:
、更新或插入当该key不存在的时候执行插入操作,当存在的时候则不管,可以使用setOnInsert
db.wyg.update({'_id': 'id'}, {'$setOnInsert': {'a': 'a'}, '$set': {'b': 'b'}}, true)
当id存在的时候,忽略setOnInsert。
当id存在的时候,如果要插入,则插入{'a': 'a'}
最后的参数true,则是指明,当update不存在的_id时,执行插入操作。默认是false,只更新,不插入。
push、setOnInsert:db.cswuyg.update({"_id": "abc"}, {$push: {"name": "c"}, $setOnInsert: {"cc":"xx"}}, true)
、计算DB中collection的数量db.system.namespaces.count()
、增加数字,采用$incdb.cswuyg.update({"a.b": {$exists: true}}, {$inc: {'a.b': 2}})
也就是对象a.b的值,增加了2
注意$inc只能用于数值。
、删除某个keydb.cswuyg.update({'_id': 'c'}, {$unset: {'b': {$exists: true}}})
{ "_id" : "c", "a" : { "b" : }, "b" : 7 }
转变为:
{ "_id" : "c", "a" : { "b" : } }
、增加key:valuedb.cswuyg.update({'_id': 'z'}, {'$set': {'hello': 'z'}})
{ "_id" : "z", "b" : 1 }
转变为:
{ "_id" : "z", "b" : 1, "hello" : "z" }
、删除数据库、删除表删除数据库:db.dropDatabase();
删除表:db.mytable.drop();
、查找到数据只看某列只显示key名为D的数据:db.test.find({}, {D: 1})
、查看分片存储情况(1)所有DB的分片存储信息,包括chunks数、shard key信息:db.printShardingStatus()
(2)db.collection.getShardDistribution() 获取collection各个分片的数据存储情况
(3)sh.status() 显示本mongos集群所有DB的信息, 包含了Shard Key信息
、查看collection的索引db.cswuyg.getIndexes()
、开启某collection的分片功能1. ./bin/mongo ?port
2. mongos> use admin
3. switched to db admin
4. mongos> db.runCommand({'enablesharding"' 'test'})
5. { "ok" : 1 }
开启user collection分片功能:
1. mongos> db.runCommand({'shardcollection': 'test.user', 'key': {'_id': 1}})
{ "collectionsharded" : "test.user", "ok" : 1 }
、判断当前是否是shard集群isdbgrid:用来确认当前是否是 Sharding Cluster
、$addToSet、$each插入数组数据mongos> db.cswuyg.find()
{ "_id" : "wyg", "a" : "c", "add" : [ "a", "b" ] }
mongos> db.cswuyg.update({"_id": "wyg"}, {"$set": {"a": "c"}, "$addToSet": {"add": {"$each" :["a", "c"]}}}, true)
mongos> db.cswuyg.find()
{ "_id" : "wyg", "a" : "c", "add" : [ "a", "b", "c" ] }
$each是为了实现list中的每个元素都插入,如果没有$each,则会把整个list作为一个元素插入,变成了2维数组。
$addToSet会判断集合是否需要排重,保证集合不重。$push可以对数组添加元素,但它只是直接插入数据,不做排重。
eg:db.test.update({"a": 1}, {$push: {"name": {$each:["a", "c"]}}})eg:db.test.update({"a": 1}, {$addToSet: {"name": {$each: ["a", "d"]}}})
不去重插入 pushAll
> db.push.insert({"a": "b", "c": ["c", "d"]})
> db.push.find()
{ "_id" : ObjectId("e4befdfbc"), "a" : "b", "c" : [ "c", "d" ]
}
> db.push.update({"a":"b"}, {$pushAll:{"c": ["z", "d"]}})
> db.push.find()
{ "_id" : ObjectId("e4befdfbc"), "a" : "b", "c" : [ "c", "d",
"z", "d" ] }
pushAll跟push类似,不同的是pushAll可以一次插入多个value,而不需要使用$each。
、刷新配置信息db.runCommand("flushRouterConfig");
、批量更新db.xxx.update({"_id": {$exists: 1}}, {$set: {"_" : ISODate("--T: :Z")}}, true, true)
最后一个参数表示是否要批量更新,如果不指定,则一次只更新一个document。
、dump DBmongodump支持从DB磁盘文件、运行中的MongoD服务中dump出bson数据文件。
(1)关闭MongoD之后,从它的DB磁盘文件中dump出数据(注:仅限单实例mongod):
mongodump --dbpath=/home/disk1/mongodata/shard/ -d cswuyg -o /home/disk2/mongodata/shard
参考:
-h xxxhost --port --db cswuyg --collection test -q "{D: {$gte: {$date: `date -d "" +%s`}, $lt: {$date: `date +%s`}}}"
mongodump -dbpath=/home/disk3/mongodb/data/shard1/ -d cswuyg -c test -o /home/disk9/mongodata/shard1_2/ -q "{_:{$gte:{$date:`date -d "" +%s`}, $lt: {$date: `date -d "" +%s`}}}"
dump出来的bson文件去掉了索引、碎片空间,所有相比DB磁盘文件要小很多。
、restore DBrestore的时候,不能先建索引,必须是restore完数据之后再建索引,否则restore的时候会非常慢。而且一般不需要自己手动建索引,在数据bson文件的同目录下有一个索引bson文件(system.indexes.bson),restore完数据之后会mongorestore自动根据该文件创建索引。
(1)从某个文件restore
mongorestore --host xxxhost --port --db cswuyg --collection cswuyg ./cswuyg_/cswuyg/cswuyg_bak.bson
(2)从目录restore
./mongorestore --port /home/disk2/mongodata/shard/
(3)dump 和 restore configure server:
mongodump --host xxxhost --port --db config -o /home/work/cswuyg/test/config
mongorestore --host xxxhost --port /home/work/cswuyg/test/config
、创建索引
看看当前的test collection上有啥索引:
当前只有_id这个默认索引,我要在test collection上为 index 字段创建索引:mongos> db.test.ensureIndex({"index": 1})创建完了之后,再看看test collection上的索引有哪些:
创建索引,并指定过期时间:db.a.ensureIndex({'_':-1}, {expireAfterSeconds: }) Second.
修改过期时间: db.runCommand({"collMod": "a", index: {keyPattern:{"_": -1}, expireAfterSeconds: }})
、删除索引db.post.dropIndexes() 删除post上所有索引
db.post.dropIndex({name: 1}) 删除指定的单个索引
、唯一索引问题如果集群在_id上进行了分片,则无法再在其他字段上建立唯一索引:
之所以出现这个错误是因为MongoDB无法保证集群中除了片键以外其他字段的唯一性,能保证片键的唯一性是因为文档根据片键进行切分,一个特定的文档只属于一个分片,MongoDB只要保证它在那个分片上唯一就在整个集群中唯一,实现分片集群上的文档唯一性一种方法是在创建片键的时候指定它的唯一性。
、因迁移导致出现count得到的数字是真实数字的两倍cswuyg> db.test.find({D: ISODate('--'), B: 'active'}).count()
cswuyg> db.test.find({D: ISODate('--'), B: 'active'}).forEach(function(item){db.test_count.insert(item)})
cswuyg> db.test_count.count()
解决方法: a sharded cluster, count can result in an inaccurate count if orphaned documents exist or if a chunk migration is in progress.
To avoid these situations, on a sharded cluster, use the $group stage of the db.collection.aggregate()method to $sum the documents. ”
、自定义MongoDB操作函数可以把自己写的js代码保存在某个地方,让MongoDB加载它,然后就可以在MongoDB的命令行里操作它们。
mongodb shell默认会加载~/.mongorc.js文件
例如以下修改了启动提示文字、左侧提示文字,增加了my_show_shards shell函数用于显示当前sharded collection的chunks在各分片的负载情况:
、关闭mongod
mongo admin --port --eval "db.shutdownServer()"
、查看chunks信息
eg: 进入到config db下,执行
db.chunks.find()
、预分片参考
"xx_config")
use xx_config_
db.dropDatabase();
远程拷贝DB :
db.copyDatabase(fromdb, todb, fromhost, username, password)
db.copyDatabase("t_config", "t_config_v1", "xxxhost: ")
这个拷贝过程很慢。
注意,sharded的DB是无法拷贝的,所以sharded的DB也无法采用上面的方式重命名。
参考: "Your remote database is sharded through mongos."
拷贝collection:
db.collection.copyTo("newcollection")
同样,sharded的collection也无法拷贝。、聚合运算
包括:
1、pipeline;
2、map-reduce
管道:
pipeline demo
demo1,基础:cswuyg_test> db.cswuyg_test.aggregate({"$match": {"_": ISODate("--"), "$or": [{"": {"$exists": true}}, {"": {"$exists": true}}]}}, {"$group": {"_id": "$_", "": {"$sum": "$"}, "":{"$sum": "$"}}})
demo2,使用磁盘:
db.test.aggregate([{'$match': {'D': {'$nin': ['a', 'b', 'c']}, '_': {'$lte': ISODate("--"), '$gte': ISODate("--")}}}, {'$group': {'_id': {'a': '$a', 'b': '$b', 'D': '$D'}, 'value': {'$sum': 1}}}], {'allowDiskUse': true})
demo3,指定输出文档:db.cswuyg.aggregate([ {'$match': {'D': {'$nin': ['a', 'b', 'c']}, '_': {'$lte': ISODate("--"), '$gte': ISODate("--")}}}, {'$group': {'_id': {'C': '$C', 'D': '$D'}, 'value': {'$sum': 1}}}, {"$out": "cswuyg_out"}], {'allowDiskUse':true})db.b.aggregate([{$match: {a: {$size: 6}}}, {$group: {_id: {a: '$a'}}}, {$out: 'hh_col'}], {allowDiskUse: true})
注:指定输出文档,只能输出到本DB下。
aggregate练习:
pymongo代码:
[{'$match': {u'I': {u'$in': [XXX']}, u'H': u'id', u'': {u'$exists': True}, '_':{'$lte': datetime.datetime(, 6, 1, , , ), '$gte': datetime.datetime(, 6, 1, 0, 0)}}}, {'$group': {'_id': {u'': u'$', u'G': u'$G'}, 'value': {'$sum': 1}}}]
shell下代码:
db.test.aggregate([{$match: {_:ISODate("--"), "H": "id", "": {"$exists": true}, "I": "XXX"}}, {$group: {_id: {"": "$", "G": "$G"}, "value": {"$sum": 1}}}], {allowDiskUse:true})
、修改Key:Value中的Value
给字段B的值加上大括号'{':
db.test.find({_:ISODate("--")}).forEach(function(item){if(/{.+}/.test(item["B"])){}else{print(item["B"]);db.test.update({"_id": item["_id"]}, {"$set": {"B": "{" + item["B"] + "}"}})}})
、修改primary shard
db.runCommand({"movePrimary": "test", "to": "shard"})
这样子test DB 里的非sharded cocllection数据就会被存放到shard中,非空DB的话,可能会有一个migrate的过程。
、 mongodb默认开启autobalancer
balancer是sharded集群的负载均衡工具,新建集群的时候默认开启,除非你在config里把它关闭掉:
config> db.settings.find()
{ "_id" : "chunksize", "value" : }
{ "_id" : "balancer", "activeWindow" : { "start" : ":", "stop" : ":" }, "stopped" : false}
activeWindow指定autobalancer执行均衡的时间窗口。
stopped说明是否使用autobalancer。
手动启动balancer:sh.startBalancer()
判断当前balancer是否在跑:sh.isBalancerRunning()
、MongoDB插入性能优化
插入性能:W的数据,在之前没有排序就直接插入,耗时4小时多,现在,做了排序,插入只需要5分钟。排序对于单机版本的MongoDB性能更佳,避免了随机插入引发的频繁随机IO。
排序:在做分文件排序的时候,文件分得越小,排序越快,当然也不能小到1,否则频繁打开文件也耗费时间。
、MongoDB数组操作
1、更新/插入数据,不考虑重复值:
mongos> db.test.update({"helo":"he2"}, {"$push": {"name":"b"}})
多次插入后结果:
{ "_id" : ObjectId("a7aa2beaebcf"), "helo" : "he2", "name" : [ "a", "b", "b" ] }
2、更新/插入数据,保证不重复:
mongos> db.test.update({"helo":"she"}, {"$addToSet": {"name":"b"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
多次插入后结果:
{ "_id" : ObjectId("dd6e1bcbdefd"), "helo" : "she", "name" : [ "b" ] }
保证只有一个值。
3、数组元素个数:
$size 用来指定数组的元素个数,显示fruit数组长度为3的document:
mongos> db.a.find({"fruit": {$size: 3}})
{ "_id" : ObjectId("bcd3addb"), "fruit" : [ "apple", "orange", "cherry" ] }
、更换Key: Value中的Key
verRelease 换为 TEST
db.test.find().forEach(function(item){db.test.update({_id:item["_id"]}, {"$set": {"TEST": item["verRelease"]}}, {"$unset":{"verRelease":{"exists":true}}})})
或者更新部分修改为:
db.test.update({D : ISODate("--")}, {$rename : {"AcT": "AM"}}, false, true)
、手动在shell下moveChunk
config> sh.moveChunk("xx.yy", { "_id" : { "D" : ISODate("--T::Z"), "id" : "3f" } }, "shard")
如果出现错误,参考这里:可能需要重启
2.4切换到2.6之后,出现数据没有插入,pymongo代码:
update_obj = {"$set" : {"a": 1}}
update_obj["$inc"] = inc_objs
update_obj["$push"] = list_objs
db.test.update({"_id": id}, update_obj, True)
2.6里,inc如果是空的,则会导致整条日志没有插入,2.4则inc为空也可以正常运行。
、格式化json显示
db.collection.find().pretty()
、更新replica集群的域名信息
、不要直接修改local.system.replset
不要直接修改local.system.replset,因为他只能修改本机器的本地信息。
但是如果出现了:
这样的错误,那就要修改本机的local.system.replset,然后重启。
、排重统计(1)aggregate
result = db.flu_test.aggregate([{$match: {_: ISODate("--")}}, {$group:{_id:"$F", value: {$sum:1}}}], {allowDiskUse:true})
result.itcount()
(2)distinct
flu_test> db.flu_test.distinct('F', {_:ISODate("--")})但是,由于distinct将结果保存在list中,所以很容易触发文档超过MB的错误:--T::.+ distinct failed: {"errmsg" : "exception: distinct too big, mb cap","code" : ,"ok" : 0} at src/mongo/shell/collection.js:非排重文档量统计:
mongos> count = db.flu_test.aggregate([{$match:{_:ISODate("--")}}, {$group:{_id:null, value: {$sum:1}}}], {allowDiskUse:true})
{ "_id" : null, "value" : }
、pymongo优先读取副本集Secondary节点优先读取副本集Secondary节点,可以减少primary节点负担,在primary节点跟secondary节点同步延迟较短、业务对数据不要求实时一致时可以利用副本集做读写分离和负载均衡。
副本集集群的读取有这几种使用方式:
primary: 默认参数,只从主节点读取;primaryPreferred: 大部分从主节点上读取,主节点不可用时从Secondary节点读取;secondary: 只从Secondary节点上进行读取操作;secondaryPreferred: 优先从Secondary节点读取,Secondary节点不可用时从主节点读取;nearest: 从网络延迟最低的节点上读取。
(1)测试1 优先从secondary读取数据:
(2)测试2 直接连接某Secondary节点读取数据:
参考:
pymongo.ReadPreference.SECONDARY_PREFERRED功能。
..补充:
、为副本集设置标签可以为副本集中的每个成员设置tag(标签),设置标签的好处是后面读数据时,应用可以指定从某类标签的副本上读数据。
参考: Cluster,shard是Replica Set。升级比较简单,只需要逐步对每一个副本都执行存储引擎升级即可,不影响线上服务。
升级时,只在启动命令中添加:--storageEngine wiredTiger。
步骤:首先,下掉一个副本;然后,把副本的磁盘文件删除掉;接着,在该副本的启动命令中添加--storageEngine wiredTiger后启动。这就升级完一个副本,等副本数据同步完成之后,其它副本也照样操作(或者处理完一个副本之后,拷贝该副本磁盘文件替换掉另一个副本的磁盘文件)。风险:如果数据量巨大,且有建索引的需求,容易出现内存用尽。
分片集群的configure server可以不升级。
升级之后磁盘存储优化效果极度明显,GB的数据会被精简到1.3GB。
升级后的磁盘文件完全变了,所以不同存储引擎下的磁盘文件不能混用。
升级参考: collection的大小,oplog是操作记录,它是一个capped collection,在副本集群中,设置得太小可能导致secondary无法及时从primary同步数据。默认情况下是磁盘大小的5%。但是,如果这个字段设置得太大,可能导致暴内存,oplog的数据几乎是完全加载在内存中,一旦太大,必然暴内存,导致OOM。而且因为这个collection是capped,MongoDB启动之后无法修改其大小。
深究从MongoDB的ObjectId中获取时间信息 MongoDB默认使用_id字段作为主键,类型为ObjectId。ObjectId的生成有一定的规则,详情可以查看这篇文章-MongoDB深究之ObjectId。如果你在写入数据库的时候忘
Windows下mongodb安装与配置三步走 前言最近在重新学习node,所以和同事一起搞了个模仿新浪微博的项目,项目刚开始,所以其他的东西就暂时先不提。这里介绍下mongodb的安装。直接搜索
Centos 7下Mongodb开机无法自启动的解决方法 前言首先下载的mongodb有bug,需要自己手动fix,这种只是对特定版本有问题,并非所有版本都有这个问题,SeLinux另外,一定要把selinux设置为disabled或者per
标签: mongodb使用场景总结
本文链接地址:https://www.jiuchutong.com/biancheng/312617.html 转载请保留说明!上一篇:MongoDB使用小结:一些不常见的经验分享(mongodb项目使用说明)
友情链接: 武汉网站建设