用于记录文档结构的数据。
数据库:
db.stats() //统计数据库信息db.dropdatabase() //删除数据库
基本操作:
插入文档:
db.collections.insert(<documents or array>, //插入多条文档用中括号相当于数组形式{//可选字段writeConcern:<document>, //自定义出错确认级别 一种捕捉机制ordered:<boolean> //值为false 忽略文档错误 继续无序插入} //值为true 有序插入 若文档错误 命令直接返回)//一条语句插入db.goods.insertOne()//多条语句插入db.goods.insertMany()//有序的插入多条文档db.goods.insert([{_id:10,item:"语文",price:20},{_id:10,item:"数学",price:20},{_id:10,item:"英语",price:20}],{ordered:true} //有序插入 中途有错则返回不插入)//自定义写出错误级别db.goods.insert{{_id:1,item:"大学语文",price:50},{writeConcern:{w:"majority",wtimeout:5000}} //定义超5秒未完成命令退出执行}//用变量形式插入文档document=({name:"Java",price:32})db.goods.insert(document)
查询文档
db.collection.find(<query>, //查询条件[projection] //可选 指定需要返回的指定字段)//查询集合所有文档db.goods.find().pretty()
//模糊查询可通过//与^$实现db.dev.find({title:/a/}) //查询文档中title的值含有a的内容db.dev.find({title:/^s/}) //查询文档中title的以s开头的内容db.dev.find({title:/g$/}) //查询文档中title的以g结尾的内容//若查询不想显示id值 并指定显示值db.good.find(){{name:"大学语文"}, //查询条件{name:1,price:1,_id:0} //1表示显示 0表示不显示}//查询返回值游标操作var showCursor=db.goods.find()showCursor.forEach(printjson); //打印显示游标的集合//limit和skipdb.goods.find().limit(number) //返回指定数量的文档db.goods.find().skip(2) //显示从第三条开始以后的文档注:可以使用 skip函数 和 limit函数 实现mongodb的分页查询 但它会扫描全部文档再返回 效率太低了 不推荐使用//$in运算符实现 或 条件查找db.goods.find({course:{$in:["java","c语言"]}}) //查找课程是Java或c语言的课程//sort()函数通过参数指定排序的字段 1表示升序 -1表示降序db.students.find({score:{$type:"number"}}).sort({score:1}) //查询score为number类型的文档 并对score做升序//count()函数用来统计查询结果数db.students.find({$and:[{major:"计算机应用技术"},{score:{$gte:80}}]}).count()
//$gt大于操作符 $lt小于操作符//$gte大于等于操作符 $lte小于等于操作符//$eq等于操作符 $ne不等于操作符db.goods.find({price:{$gt:3,$lt:33}}) //查询 大于3小于33的范围值//$and操作符:表示多条件间的并且关系db.goods.find({$and:[{price:{$gt:3}},{price:{$lt:33}}]}) //查询 大于3小于33的范围值//$or操作符:表示多条件间的或者关系db.goods.find({$or:[{price:{$gt:3}},{price:{$lt:33}}]}) //查询大于3或者小于33的数据//$or 和 $and 联用 例:查询title为test5 且size=500,或size<400的文档db.dev.find({$or:[{$and:[{title:{$eq:"test5"}},{size:500}]},{size:{$lt:400}}]})//$type操作符:检索集合中匹配的数据类型 并返回结果db.goods.find({price:{$type:"number"}})注:typeof 数据 可在命令行中判断数据是什么类型的
更新文档
db.collection.update(query, update, options)//或db.collection.update(<query>, //查询条件<update>, //更改操作{upsert: <boolean>, //更新插入操作multi: <boolean>, //多条记录全部更新操作writeConcern: <document>, //自定义错误级别collation: <document>, //指定特定国家语言的更新归类规则arrayFilters: [ <filterdocument1>, ... ], //筛选文档数组hint: <document|string> //指定用于支持查询谓词的索引的文档或字符串} )
//$set操作符:指定一个键更新其值且不改变其它值 若键不存在则创建db.students.update({name:"张三"},{$set:{name:"李四"}})//$inc操作符:修改数值 做加法运算(可以是负数,小数)db.students.update({name:"张三"},{$inc:{score:-20}})//$mul操作符:修改数值 做乘法运算db.students.update({name:"张三"},{$mul:{score:0.5}})//$rename:修改字段的键名db.students.update({name:"张三"},{$rename:{"name":"姓名"}})//$unset操作符:删除一个字段(键)db.students.update({name:"l"},{$unset:{course:""}})//$push操作符:向文档的某个数组类型的键添加一个数组元素,不过滤重复的数据db.goods.update({title:"苹果"},{$push:{tags:["今日"]}})//$slice:在$push操作时 限制数组元素的个数 ($slice必须和$each一起使用)db.students.update({_id: 1},{$push:{scores:{$each:[ 80, 78, 86],$slice:-5}}}) //添加新元素 使用$slice截取后面五个元素//$pop操作符:删除数据元素 一次只能从数组内删除一个元素db.goods.update({title:"苹果"},{$pop:{tags:1}}) //1表示从数组的尾部删除 -1表示从头部删除//$pull操作符:从数组中删除满足条件的元素db.goods.update({title:"苹果"},{$pull:{tags:"今日"}})//$pullAll操作符:从数组中删除满足条件的多个元素db.goods.update({title:"java"},{$pullAll:{tags:["javase","javame"]}})//$addToSet:添加值到一个数组中去,如果数组中已经存在该值那么将不会有任何的操作db.test.update({_id:1},{$addToSet:{letters:["a","c"]}}) //a,c将作为一个字段放入//$each:与$addToSet配合使用,$each修饰符允许$addToSet操作符添加多个元素到数组字段中db.test.update({_id:1},{$addToSet:{letters:{$each:["d","e","f"]}}})//$min操作符:将给出的值与当前文档字段值比较,若给定值最小时则修改为给定值($max相反)db.students.update({name:"金九"},{$min:{score:70}})//ISODate 用于更新当前文档时间字段的值db.students.update({_id:"1001"},{lastime:ISODate("2021-3-11")})//多条文档修改用$multi//upsert:增加文档字段db.order.update({_id:1001},{$set:{"detail.2":{name:"西瓜",price:27}}},{upsert:true})//$in:查询满足条件的文档db.teachers.find({prof:{$in:["助教","副教授"]}}) //查询职称是否是助教或副教授的文档//$wheredb.students.find({$and:[{"$where":"this.score<=60"},{sex:"女"},{age:{$gte:19,$lte:20}}]})//$size操作符db.students.find({community:{$size:1}},{name:1,sex:1,age:1,community:1}) //查询只加入了一个协会的学生姓名、性别、年龄和协会信息
//修改一条文档里面的数组和嵌套文档db.order.insert({_id:1001,title:"商品购物单",amount:90,detail:[{name:"葡萄",price:60},{name:"面粉",price:30}],overview:{shop:"商务",shopno:1,addres:"大厦"}})db.order.update({_id="1001"}, //id 的值记得用引号括上{$set:{"detail.1":{name:"大米",price:60},//修改数组用下标"overview.addres":"上海路" //修改内嵌文档要直接指定}})
删除文档
db.collection.remove(<query>, //删除条件{justone:<boolean>,writeConcern:<document>,collation:<document>})
db.dev.remove({title:"dev"},1) //1 是justone参数条件 表示只删除一条数据
注:remove()方法并不会真正释放空间,需要执行db.repairDatabase()来回收磁盘空间
deleteOne()函数 删除文档后会自动释放磁盘空间
db.dev.deleteOne({title:"dev"}) //删除一条文档db.dev.deleteMany({title:"dev"}) //删除多个满足条件的文档db.dev.deleteMany({}) //删除集合中的所有文档
索引
db.collection.createIndex({创建索引的键:排序规则...},{创建索引参数})
//查看索引db.collection.getIndexes() 或 db.collection.getIndexSpecs()//查看索引键db.collection.getIndexKeys()//查看索引大小db.collection.totalIndexSize([detail](可选参数)) //参数传入0或false则显示索引总大小值 传入其它值则会显示每个索引大小
交叉索引
为一个集合的多个字段分别创建索引,在查询时通过多个字段作为查询条件
复合索引
针对多个字段联合创建索引,先按第一个字段排序,第一个字段相同再按第二个字段排序,依次类推
不仅满足多个字段组合的查询,还满足符合匹索引前缀的查询
//格式db.collection.createIndex({索引键名:排序规则,索引键名:排序规则..})
多Key索引
当索引的字段为数组时,创建出来的索引就是多Key索引,它会为每个元素建立一条索引
db.collcetion.createIndex({数组键名:排序规则})
索引额外属性
background (boolean型) :后台建立索引,以便创建索引时不阻止其它数据库活动
unique (boolean型) :**创建唯一索引 保证索引对应的键不会出现相同的值(比如:_id索引)
db.collcetion.createIndex({索引键名:排序规则},{unique:true})
partialFilterExpression: 部分索引 为满足指定的筛选条件的文档创建索引
db.collcetion.createIndex({索引键名:排序规则},{partialFilterExpression:{键名:{匹配条件:条件值}}})//为学生年龄大于18岁的创建部分索引db.students.createIndex({age:1},{partialFilterExpression:{age:{$gt:18}}})
注:如果指定partialFilterExpression和unique,那么唯一性约束只适合于满足筛选条件(部分索引)的文档。具有唯一性约束的部分索引不会阻止不符合唯一约束且不符合过滤条件的文档插入(比如上例:小于18的可以不满足唯一约束)
覆盖索引查询
所有的查询字段是索引的一部分,所有的查询返回字段在同一个索引中。
直接从索引中提取数据,很快的数据查询
db.students.find({age:18},{major:1,_id:0}) //不包含id字段 在查询结果集中排除它
查询计划
//explain()函数 使用查询计划分析索引的使用情况来决定如何优化db.collection.find().explain()
索引建立事项:
建立合适的索引:为每一个常用的查询结构建立合适的索引。复合索引是创建的索引由多个字段组成,交叉索引是每个字段单独建立索引,在查询的适合组合查找。 交叉索引的查询效率较低,在查询使用到多个字段时,尽量使用复合索引。
字段的排序顺序:当符合索引包含匹配条件和范围条件时,匹配条件应该放在范围条件的前面
对现有的大表建立索引时,采用后台运行方式:建立索引时数据库会停止该集合的所有读写操作,数据量大时,应该采用后台运行的方式
正则查询
//格式db.collection.find({字段名:正则表达式})或db.collection.find({字段名:{$regex:正则表达式,$option:正则选项}})正则表达式格式: /xxx/正则选项:i 不区分大小写m 多行查询,如果内容中不存在换行符号(\n)或条件上没有(start/end)x 正则表达式中的非转义的空白字符将被忽略 需要$regex和$option语法配合使用s 允许点字符(匹配包括换行符在内的所有字符) 需要$regex和$option语法配合使用i m s x可以组合使用
//以陈开头的姓名查找db.students.find({name:/^陈/})或 db.students.find({name:{$regex:/^陈/}})//以s结尾的查找db.students.find({name:/s$/})//查询字段中包含 se 的数据db.students.find({name:/se/})//以s开头的查找 且忽略大小写db.students.find({name:/^s/i})//以s开头的查找 以m结尾的数据db.students.find({name:/^s.*g$/}) //*表示任意多个字符//以s或t开头的查找db.students.find({name:{$in:[/^s/,/^t/]}})//不是以s或t开头的查找db.students.find({name:{$nin:[/^s/,/^t/]}})//不是以s开头的查找db.students.find({name:{$not:/^s/}})
聚合查询
管道操作
聚合管道将MongoDB文档在一个管道处理完成后将结果传递给下一个管道处理。管道操作可以重复的。
管道操作符:$match,$group,$sort,$limit,$skip,$unwind
管道操作符只能用于计算当前聚合管道的文档,不能处理其它的文档
aggregate()函数用来完成一些聚合查询,比如处理统计,平均值,求和等 并返回计算后的结果
db.collection.aggregate( //_id字段必须有[{$group:{_id:"$分组键名","$分组键名"..别名:{聚合运算符:"$运算列"}}},{条件筛选:{键名:{运算条件:运算值}}}])
//$sum 求和db.students.aggregate([{$group:{_id:null,count:{$sum:1}}}]) //查询集合中有多少文档//查询students集合中所有成绩的值的总和 $score表示score字段的值db.students.aggregate([{$group:{_id:null,total:{$sum:"$score"}}}])//对每一个name进行分组并且计算每组中的score的和db.students.aggregate([{$group:{_id:"$name",total:{$sum:"$score"}}}])
//查询students中有多少学生成绩大于80 $match放在前面相当于where子句 即条件筛选db.students.aggregate([{$match:{score:{$gt:80}}},{$group:{_id:null,total:{$sum:1}}}])//查询students中 以name分组计算出每组score的总和,并过滤掉总和小于80的文档 $match放后面相当于having子句db.students.aggregate([{$group:{_id:"$name",total:{$sum:"$score"}}},{$match:{total:{$gt:80}}}])//查询students集合中score最大的文档 $maxdb.students.aggregate([{$group:{_id:null,maxScore:{$max:"$score"}}}])//查询students集合中score最小的文档 $mindb.students.aggregate([{$group:{_id:null,minScore:{$min:"$score"}}}])//查询students集合中score的平均值 $avgdb.students.aggregate([{$group:{_id:null,avgScore:{$avg:"$score"}}}])//查询students集合 按照score分组并返回name,如果score相同则数组返回name $pushdb.students.aggregate([{$group:{_id:"$score",name:{$push:"$name"}}}])//查询students集合 将数组中的内容拆分显示 $unwinddb.students.aggregate([{$unwind:"$community"}])
//$project操作符 用来做聚合投影操作//对students集合中的数组进行拆分 并且只显示相应字段db.students.aggregate([{$unwind:"$community"},{$project:{_id:0,name:1,community:1}}]) //或name:"$name"//$project 字符串处理//对students集合中的数组进行拆分 并且只显示相应字段 name转为小写db.students.aggregate([{$unwind:"$community"},{$project:{_id:0,name:{$toLower:"$name"},community:1}}])//对students集合中的数组进行拆分 并且将相应字段拼接 $concatdb.students.aggregate([{$unwind:"$community"},{$project:{_id:0,habb:{$concat:["$name","-","$community"]}}}])//对students集合中的数组进行拆分 并且只显示相应字段的前几个字符 $substrdb.students.aggregate([{$unwind:"$community"},{$project:{_id:0,habb:{$substr:["$community",0,3]}}}])注:$substr 只能匹配ASCII的数据,对中文要使用$substrCP//查询students集合中的数据 并做算术运算操作$add:加 $subtract:减 $multiply:乘 $divide:除 $mod:模(是否能整除)//这是对投影数据的算术运算 并没有改变数据真实的值db.students.aggregate([{$project:{_id:0,NewScore:{$add:["$score",1]}}}])
$project—日期操作
//插入日期db.studnets.insert({time:new Date()}) //插入当前日期//插入指定的时间 日期格式yyyy-MM-ddThh:mm:ssdb.students.insert({time:new Date("2018-2-9T9:9:9Z")}) //使用new date()创建时间必须给出标准的日期格式或db.students.insert({time:ISODate("2018-2-9 9:9:9")}) //可以不用给出标准日期//查询大于指定时间的数据db.students.find({time:{$gt:ISODate("20180109")}})//查询时间数据 显示brith的各部分字段$hour时 $minute分 $second秒 $dayOfweek周几 $week全年的第几周 $dayOfYeardb.students.aggregate([{$match:{name:"admin"}},{$project:{年:{$year:"$brith"},月:{$month:"$brith"},日:{$dayOfMonth:"$brith"}}}])//自定义日期格式db.students.aggregate([{$match:{name:"admin"}},{$project:{时间:{$dateToString:{format:"%Y年%m月%d日 %H:%M:%S",date:"$brith"}}}}])
