MongoDB 基础知识

2020-02-26  本文已影响0人  Minnakey
基础
> show bds  
# admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这 个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
# local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
# config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
> use db_name
> db.dropDatabase()
> dbname.system.*
> db.createCollection(name, options)
> db.createCollection("mycol", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } )  #创建固定集合 mycol,整个集合空间大小 6142800 KB, 文档最大个数为 10000 个
> db.collection.drop()
>  show collections
> db.mycol2.insert({"name" : "MongoDB"})  # insert 自动创建集合
> db.col.find()

> document=({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
});
> db.col.insert(document)
> db.collection.insertOne({"a": 3})
> db.collection.insertMany([{"b": 3}, {'c': 4}])

> var arr = [];
for(var i=1 ; i<=20000 ; i++){
    arr.push({num:i});
}
> db.numbers.insert(arr);
# 插入文档你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。
> db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } ); //只更新第一条记录
> db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );  //全部更新> > db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false ); //只添加第一条
> db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true );  //全部添加进去
> db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },{upsert:false},{multi:true} );  //全部更新
> db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} },false,false ); //只更新第一条记录
> db.collection.save(
   <document>,
   {
     writeConcern: <document>
   }
)
> db.col.find().pretty()
> use test
> db.test_collection.insert( [
{"name":"abc","age":"25","status":"zxc"},
{"name":"dec","age":"19","status":"qwe"},
{"name":"asd","age":"30","status":"nmn"},
] )
> db.test_collection.updateOne({"name":"abc"},{$set:{"age":"28"}})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
> db.test_collection.find()
{ "_id" : ObjectId("59c8ba673b92ae498a5716af"), "name" : "abc", "age" : "28", "status" : "zxc" }
{ "_id" : ObjectId("59c8ba673b92ae498a5716b0"), "name" : "dec", "age" : "19", "status" : "qwe" }
{ "_id" : ObjectId("59c8ba673b92ae498a5716b1"), "name" : "asd", "age" : "30", "status" : "nmn" }
> db.test_collection.updateMany({"age":{$gt:"10"}},{$set:{"status":"xyz"}})
{ "acknowledged" : true, "matchedCount" : 3, "modifiedCount" : 3 }
> db.test_collection.find()
{ "_id" : ObjectId("59c8ba673b92ae498a5716af"), "name" : "abc", "age" : "28", "status" : "xyz" }
{ "_id" : ObjectId("59c8ba673b92ae498a5716b0"), "name" : "dec", "age" : "19", "status" : "xyz" }
{ "_id" : ObjectId("59c8ba673b92ae498a5716b1"), "name" : "asd", "age" : "30", "status" : "xyz" }

WriteConcern.NONE:没有异常抛出
WriteConcern.NORMAL:仅抛出网络错误异常,没有服务器错误异常
WriteConcern.SAFE:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。
WriteConcern.MAJORITY: 抛出网络错误异常、服务器错误异常;并等待一个主服务器完成写操作。
WriteConcern.FSYNC_SAFE: 抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。
WriteConcern.JOURNAL_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。
WriteConcern.REPLICAS_SAFE:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作。

> db.col.update({"_id":"56064f89ade2f21f36b03136"}, {$set:{ "test2" : "OK"}})  #数据存在则更新
> db.col.find()
> db.col.update({"_id":"56064f89ade2f21f36b03136"}, {$unset:{ "test2" : "OK"}})
> db.col.find()
> db.collection.update({'title':'MongoDB 教程'}, {$setOnInsert: {'title':'MongoDB'}}) #数据存在时不进行操作
# db.collection.find(query, projection)
> db.col.find({"by":"mongodb"}).pretty()  # =
> db.col.find({"likes":{$lt:50}}).pretty()  # <
> db.col.find({"likes":{$lte:50}}).pretty()  # <=
> db.col.find({"likes":{$gt:50}}).pretty()  # >
> db.col.find({"likes":{$gte:50}}).pretty()  # >=
> db.col.find({"likes":{$ne:50}}).pretty()  # !=
> db.col.find({"likes": {$gt:50}, $or: [{"by": "MongoDB"},{"title": "MongoDB 教程"}]}).pretty()
db.collection.find(query, {title: 1, by: 1}) # inclusion模式 指定返回的键,不返回其他键
db.collection.find(query, {title: 0, by: 0}) # exclusion模式 指定不返回的键,返回其他键
querydb.collection.find({}, {title: 1})  # 若不想指定查询条件参数 query 可以 用 {} 代替,但是需要指定 projection 参数:
db.posts.find( {  qty: { $gt: 50 ,$lt: 80}} )  # qty 大于 50 小于 80 
db.col.find({title:/教/})  #查询 title 包含"教"字的文档
db.col.find({title:/^教/})  #查询 title 字段以"教"字开头的文档
db.col.find({title:/教$/})  #查询 titl e字段以"教"字结尾的文档
db.col.find({"title" : {$type : 2}})  # 1 Double, 3 Object, 4 Array, 5 Binary data,  7 Object id, 8 Boolean, 9 Date, 10 Null, 11 Regular Expression, 13 JavaScript, 14 Symbol, 16 32-bit integer, 17 Timestamp, 18 64-bit integer
db.col.find({"title" : {$type : 'string'}})  
db.col.find().skip(10).limit(100)  # sql 中limit (10,100)
db.test.sort({"amount":1}).skip(100000).limit(10)  # 183ms  sort :1 为升序排列,而 -1 是用于降序排列, 先 sort(), 然后是 skip(),最后是显示的 limit()  
db.test.find({amount:{$gt:2399927}}).sort({"amount":1}).limit(10)  # 53ms
# remove 不会真正释放空间
> db.col.remove({'title':'MongoDB 教程'})
# 推荐使用delete
> db.inventory.deleteMany({})
> db.inventory.deleteMany({ status : "A" })
> db.inventory.deleteOne( { status: "D" } )
#回收磁盘空间
> db.repairDatabase()  
> db.runCommand({ repairDatabase: 1 }) 
### 索引
db.col.createIndex({"title":1,"description":-1})  #复合索引
db.values.createIndex({open: 1, close: 1}, {background: true}) #background:true 的选项,让创建工作在后台执行
db.col.getIndexes()  #查看集合索引
db.col.totalIndexSize()  #查看集合索引大小
db.col.dropIndexes()  #删除集合所有索引
db.col.dropIndex("索引名称")  #删除集合指定索引
#利用 TTL 集合对存储的数据进行失效时间设置
db.col.createIndex({"createDate": 1},{expireAfterSeconds: 180})
db.col.createIndex({"ClearUpDate": 1},{expireAfterSeconds: 0})
## 聚合
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])  // min, max, avg
db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])  //在结果文档中插入值到一个数组中
db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) //在结果文档中插入值到一个数组中,但不创建副本。
db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) //根据资源文档的排序获取第一个文档数据。
db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])  //根据资源文档的排序获取最后一个文档数据
## 管道
db.article.aggregate( { $project : {  _id : 0 , title : 1 ,author : 1 }});
db.articles.aggregate( [
                        { $match : { score : { $gt : 70, $lte : 90 } } },
                        { $group: { _id: null, count: { $sum: 1 } } }
                       ] );
db.article.aggregate( { $skip : 5 });
db.getCollection('m_msg_tb').aggregate(
[
    {$match:{m_id:10001,mark_time:{$gt:new Date(2017,8,0)}}},
    {$group: {_id: {$dayOfMonth:'$mark_time'},pv: {$sum: 1}}},
    {$sort: {"_id": 1}}
])
时间关键字:
$dayOfYear: 返回该日期是这一年的第几天(全年 366 天)。
 $dayOfMonth: 返回该日期是这一个月的第几天(1到31)。
 $dayOfWeek: 返回的是这个周的星期几(1:星期日,7:星期六)。
 $year: 返回该日期的年份部分。
 $month: 返回该日期的月份部分( 1 到 12)。
 $week: 返回该日期是所在年的第几个星期( 0 到 53)。
 $hour: 返回该日期的小时部分。
 $minute: 返回该日期的分钟部分。
 $second: 返回该日期的秒部分(以0到59之间的数字形式返回日期的第二部分,但可以是60来计算闰秒)。
 $millisecond:返回该日期的毫秒部分( 0 到 999)。
 $dateToString: { $dateToString: { format: , date: } }。
db.articles.aggregate([{$match:{score:{ $gt:70, $lte:90 }}},{$group:{_id: null,count:{$sum: 1 }}}]);
db.articles.aggregate([{$group:{_id: null,count:{$sum: 1 }}},{$match:{score:{ $gt:70,$lte:90 }}}]);
mongod --port 27017 --dbpath "\mongodb\data" --replSet rs0
rs.initiate() #启动一个新的副本集
rs.conf() #查看副本集的配置
rs.status() #查看副本集状态
rs.add("mongod1.net:27017")   # 副本集添加成员
db.isMaster()    #判断当前运行的Mongo服务是否为主节点

分片实例
分片结构端口分布如下:
Shard Server 1:27020
Shard Server 2:27021
Shard Server 3:27030
Shard Server 4:27031
Config Server1 :27100
Config Server2 :27101
Route Process:40000

  1. 启动Shard Server
1.创建Sharding复制集 rs0
mkdir /data/log
mkdir /data/db1
nohup mongod --port 27020 --dbpath=/data/db1 --logpath=/data/log/rs0-1.log --logappend --fork --shardsvr --replSet=rs0 &
mkdir /data/db2
nohup mongod --port 27021 --dbpath=/data/db2 --logpath=/data/log/rs0-2.log --logappend --fork --shardsvr --replSet=rs0 &
mongo localhost:27020
> rs.initiate({_id: 'rs0', members: [{_id: 0, host: 'localhost:27020'}, {_id: 1, host: 'localhost:27021'}]}) 
> rs.isMaster()

2. 创建Sharding复制集 rs1
mkdir /data/db3
nohup mongod --port 27030 --dbpath=/data/db3 --logpath=/data/log/rs1-1.log --logappend --fork --shardsvr --replSet=rs1 &
mkdir /data/db4
nohup mongod --port 27031 --dbpath=/data/db4 --logpath=/data/log/rs1-2.log --logappend --fork --shardsvr --replSet=rs1 &
> rs.initiate({_id: 'rs1', members: [{_id: 0, host: 'localhost:27030'}, {_id: 1, host: 'localhost:27031'}]})
> rs.isMaster()
  1. 启动Config Server
mkdir /data/conf1
nohup mongod --port 27100 --dbpath=/data/conf1 --logpath=/data/log/conf-1.log --logappend --fork --configsvr --replSet=conf &
mkdir /data/conf2
nohup mongod --port 27101 --dbpath=/data/conf2 --logpath=/data/log/conf-2.log --logappend --fork --configsvr --replSet=conf &
#复制集conf配置
mongo localhost:27100
> rs.initiate({_id: 'conf', members: [{_id: 0, host: 'localhost:27100'}, {_id: 1, host: 'localhost:27101'}]})
> rs.isMaster()    #查看主从关系
  1. 启动Route Process
nohup mongos --port 40000 --configdb conf/localhost:27100,localhost:27101 --fork --logpath=/data/log/route.log  --chunkSize 500 --logappend & 
# mongos启动参数中,chunkSize这一项是用来指定chunk的大小的,单位是MB,默认大小为200MB
  1. 设置分片
# mongo localhost:40000
> use admin
> db.runCommand({ addshard: 'rs0/localhost:27020,localhost:27021'})
> db.runCommand({ addshard: 'rs1/localhost:27030,localhost:27031'})
> db.runCommand({ enablesharding: 'test'})
> db.runCommand({ shardcollection: 'test.user', key: {name: 1}})
> mongodump -h dbhost -d dbname -o dbdirectory
#备份所有MongoDB数据
mongodump --host runoob.com --port 27017
mongodump --dbpath /data/db/ --out /data/backup/
#备份指定数据库的集合
mongodump --collection mycol --db test
> mongorestore -h <hostname><:port> -d dbname <path>
mongostat
mongotop 10
mongotop --locks
高级教程
{
   "_id":ObjectId("53402597d852426020000002"),
   "address": {
   "$ref": "address_home",
   "$id": ObjectId("534009e4d852427820000002"),
   "$db": "runoob"},
   "contact": "987654321",
   "dob": "01-01-1991",
   "name": "Tom Benzamin"
}

手动引用

#创建联合索引
db.users.ensureIndex({gender:1,user_name:1})
#该索引会覆盖以下查询
db.users.find({gender:"M"},{user_name:1,_id:0})
#explain 操作提供了查询信息,使用索引及查询统计等
db.users.ensureIndex({gender:1,user_name:1})
db.users.find({gender:"M"},{user_name:1,_id:0}).explain()

indexOnly: 字段为 true ,表示我们使用了索引。
cursor:因为这个查询使用了索引,MongoDB 中索引存储在B树结构中,所以这是也使用了 BtreeCursor 类型的游标。如果没有使用索引,游标的类型是 BasicCursor。这个键还会给出你所使用的索引的名称,你通过这个名称可以查看当前数据库下的system.indexes集合(系统自动创建,由于存储索引信息,这个稍微会提到)来得到索引的详细信息。
n:当前查询返回的文档数量。
nscanned/nscannedObjects:表明当前这次查询一共扫描了集合中多少个文档,我们的目的是,让这个数值和返回文档的数量越接近越好。
millis:当前查询所需时间,毫秒数。
indexBounds:当前查询具体使用的索引。

db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1})
db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain()
{ $set : { field : value } }  # $set  指定一个键并更新键值,若键不存在并创建
{ $unset : { field : 1} }  # $unset  删除一个键
{ $inc : { field : value } }  # $inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作
{ $push : { field : value } } # 把value追加到field里面去,field一定要是数组类型才行,如果field不存在,会新增一个数组类型加进去
{ $pushAll : { field : value_array } } #$pushAll 同$push,只是一次可以追加多个值到一个数组字段内
{ $pull : { field : _value } } # $pull 从数组field内删除一个等于value值
{ $pop : { field : 1 } }  # $pop 删除数组的第一个或最后一个元素
# $addToSet 增加一个值到数组内,而且只有当这个值不在数组内才增加
{ $rename : { old_field_name : new_field_name } } # $rename修改字段名称
{$bit : { field : {and : 5}}} # $bit 位操作,integer类型
# 偏移操作符 
> t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] }
> t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true )
> t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
db.users.ensureIndex({"tags":1})
db.users.find({tags:"cricket"}).explain()  // 检索集合中的字段
db.users.ensureIndex({"address.city":1,"address.state":1,"address.pincode":1})
db.users.find({"address.city":"Los Angeles","address.state":"California","address.pincode":"123"})  // 检索子文档中的字段
newObjectId = ObjectId()
ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()   //获取文档的创建时间
new ObjectId().str  //将objectid 转换成字符串
>db.collection.mapReduce(
   function() {emit(key,value);},  //map 函数
   function(key,values) {return reduceFunction},   //reduce 函数
   {
      out: collection,
      query: document,
      sort: document,
      limit: number
   }
)
db.users.mapReduce(map,reduce,{out:{inline:1}});  #这个选项只有在结果集单个文档大小在16MB限制范围内时才有效

>db.posts.mapReduce( 
   function() { emit(this.user_name,1); }, 
   function(key, values) {return Array.sum(values)}, 
      {  
         query:{status:"active"},  
         out:"post_total" 
      }
).find()
#启动全文检索
db.adminCommand({setParameter:true,textSearchEnabled:true}) 
mongod --setParameter textSearchEnabled=true

db.posts.ensureIndex({post_text:"text"})  #创建全文索引
>db.posts.find({$text:{$search:"runoob"}}) //使用全文索引
db.posts.getIndexes()  //查找索引名
db.posts.dropIndex("post_text_text")  // 删除索引
>db.posts.find({post_text:{$regex:"runoob",$options:"$i"}})  //不区分大小写的正则表达式
>db.createCollection("cappedLogCollection",{capped:true,size:10000,max:1000})
>db.cappedLogCollection.isCapped()  #判断集合是否为固定集合:
>function getNextSequenceValue(sequenceName){
   var sequenceDocument = db.counters.findAndModify(
      {
         query:{_id: sequenceName },
         update: {$inc:{sequence_value:1}},
         "new":true
      });
   return sequenceDocument.sequence_value;
}

>db.createCollection("counters")
>db.counters.insert({_id:"productid",sequence_value:0})
>db.products.insert({
   "_id":getNextSequenceValue("productid"),
   "product_name":"Apple iPhone",
   "category":"mobiles"})

恕我直言,牛逼哄哄的MongoDB你可能只会30%

上一篇 下一篇

猜你喜欢

热点阅读