MongoDB 学习笔记


MongoDB 是一种NOSQL数据库,Node.js将其作为主DB
MongoDB 包括:数据库(类似于)--数据库,集合--表,文档--行,成员--列,ObjectID自动维护--主键
所有数据都是文档形式保存的,标准json保存的
Node.js开发必需使用MongoDB
www.mongodb
安装后在安装目录下新建目录 db、log
mongod --dbpath E:/MongoDB/db //数据文件放在db目录下
mongod --dbpath E:/MongoDB/db --port=27000  //设置端口号
mongo //连接mongo 数据库
show database //查询所有数据库,会显示一个local数据库,这个数据库不使用
show dbs
新建一个mongodb.conf文件里面如下内容:
  dbpath = E:\MongoDB\db   //设置数据目录的路径
  logpath = E:\MongoDB\logmongodb.log  //设置日志信息的文件路径
  logappend = true   //打开日志输出操作
#  noauth = true  //不以授权的方式打开DB, 不需要登录密码
  auth = true//以验证的方式打开DB,需要登录密码
  port = 27001   //端口号
use admin  //切换到admin用户
db.shutdownServer()   //关闭数据库
mongod -f E:\MongoDB\mongodb.conf  //重启mongo服务
mongo --port=27001  //连接数据库 带端口号


use mldnDB //创建了数据库,只有在数据库里面保存集合数据之后才能够真正创建数据库
db.createCollection("emp") //创建一个集合
db.dept.insert({"deptno":10, "dname":"财务部","loc":"北京"});
show collections   //查看所有集合
db.dept.find();  //db.集合名称.find({若干条件})
   可以增加不规则的数据,内容随便定义,db不能查看集合结构
var deptData={"deptno":20, "dname":"研发部"};
db.dept.insert(deptData);
集合中每一行记录都会自动生成一个_id  时间戳+机器码+ PID + 计数器
db.dept.findOne();
db.dept.remove({"_id":ObjectId("123jklj23123jkj233j2jc")});


var deptData={"deptno":50, "dname":"乞讨部"};
db.dept.update({"_id":ObjectId("123jklj23123jkj233j2jc")},deptData);


db.dept.drop(); //删除集合
db.dropDatabase(); //删除当前所在的数据库
db.集合.insert({json表达式}); //增加操作,‘集合’相当于表名,‘json’就是数据
db.集合.insert([{json表达式},{json表达式}]); //保存多个数据用数组,保存了2个数


db.集合名称.find({查询条件}[{设置显示的字段}])
db.info.find({"url":"www.dml.com"},{"_id":0,"url":1}).pretty(); //查询url="www.dml.com",不显示‘_id’字段,显示url 字段。pretty漂亮的显示


关系查询:等于(key:value、$eq),大于($gt),小于($lt),大于等于($gte),小于等于($lte),不等于($ne)
db.student.find({"name":"张三"});
db.student.find({"age":{"$gt":19}}); //查询age 大于19的学生


逻辑运算:与($and)、或($or),非($not、$nor--对or求反)
db.students.find({"age":{"$gte":19, "$lte":20}});查询年龄在19到20岁的学生
db.students.find({"age":{"$ne":{"$gte":19, "$lte":20}}}); 查询age不是19到20岁的学生
db.students.find({"$or":[{"age":{"$gt":19}}, 
{"score":{"$gt":90}}]});查询年龄大于等于19 或者 分数大于90的学生


求模--$mod
{"$mod":[数字,小数位]}
db.students.find({"age":{"$mod":[20,0]}}); 对年龄求模,age对20求模 于1 的数


查询范围:"$in"(在范围中)、"$nin"(不在范围中)
db.students.find({"name":{"$in":["张三","李四"]}}); name in 张三、李四的数


数组查询:运算符:$all、$size、$slice、$elemMatch
{"$all":[内容1,内容2,..]}
student中course是一个数组列
db.students.find({"course":{"$all":["语文","数学"]}}).pretty(); //包含有"语文","数学" 的数据
db.students.find({"course.1":"数学"}).pretty(); //查询数组中第二个内容(index=1,索引下表从0开始)为数学的信息
db.students.find({"course":{"$size":2}}).pretty();//查询出只参加两门课的信息
控制数组返回的数量
db.students.find({"age":19}, {"course":{"$slice":2}}).pretty();返回年龄为19,但是只显示前两门课程(只显示数组中 第0和1两个数)
db.students.find({"age":19}, {"course":{"$slice":[1,2]}}).pretty();但是只显示中间两门课程(只显示数组中第1和第2两个数)  [1,2]‘1’为跳过量,‘2’为返回2个数


嵌套集合运算 "$elemMatch"
db.students.find({"age":{"$gte":19, "parents":{"$elemMatch":{"job":"局长"}}}})
db.students.find({"$and":[
{"age":{"$gte":19}},
{"parents":{"$elemMatch":{"job":"局长"}}}]})


判断某个字段是否存在,$exists true表示存在
db.students.find({"parents":{"$exists":true}}).pretty(); //显示有parents列的数据


条件过滤 "$where", 使用where时 索引是不起作用的,属于全表扫描
db.students.find({"$where": "this.age>20"});
db.students.find("this.age>20");
db.students.find(function(){ return this.age>20;});//属于编写一个操作函数
db.students.find({"$where": "function(){ return this.age>20;}"});//加$where就要加 {}
db.students.find({"$and": [ {"$where":"this.age>19"},
{"$where":"this.age<21"}]});


正则运算:模糊查询必需使用正则表达式,使用的是Perl语言兼容的正则表达式形式
基础语法:{key: 正则标记}
完整语法:{key: {"$regex": 正则标记,"$options": 选项}}
    对于options主要是设置正则的信息查询标记
        "i": 忽略大小写
        "m": 多行查询
        "x": 空白字符串除了被转义的或在字符类中意外的 完全被忽略
        "s": 匹配所有字符(圆点、"."),包括换行内容
    如果是直接使用(javascript), i和m 可以直接使用,而“x”和“s”必需使用"$regex"
db.students.find({"name": /谷/}) ; 查询姓名带"谷"的姓名,谷 没有双引号"
db.students.find({"name": /a/i}) ;查询name中存在a的名称,不区分大小写
db.students.find({"name": {"$regex": /a/i}}).pretty() ;//完整的格式
db.students.find({"name": /语?/}).pretty() ; //之查询出带"语文"的数据,尽量少用?


排序操作,"sort()" 升序(1),降序(-1)
db.students.find().sort({"score": -1}).pretty(); //按照成绩降序排序
自然排序:数据保存的先后顺序


数据分页显示:skip() 表示跨过多少数据行
limit(n) 取出的数据行的个数限制
db.students.find().skip(0).limit(5).sort({"age": -1}).pretty();  显示第一页,0-5条
db.students.find().skip(5).limit(5).sort({"age": -1}).pretty();  显示第二页,5-10条,跨过5条 显示5条


数据更新操作
mongodb修改函数很麻烦,如果关系型数据变更了,mongodb数据删掉从新插
语法:db.集合.update(更新条件, 新的对象数据(更新操作符) , upsert,multi);
    upsert:如果要更新的数据不存在,则增加一条新的内容(true为增加,false为不增加)
multi:表示是否只更新满足条件的第一行记录,如果设置成false只更新第一条,true为全更新。
db.students.update({"age": 19}, {"$set":{"score":100}},false,false);  将年龄是19岁的成绩都更新为100分,false为只更新一条
db.students.update({"age": 19}, {"$set":{"score":100}},false,true);  将年龄是19岁的成绩都更新为100分,true为都更新
db.students.update({"age": 30},{"$set":{"name":"不存在"}},true,false); 由于没有年龄是30的数据,所以此时相当于数据创建,true为没有则创建
使用save()操作,找到为更新,找不到则插入一条(用_id不会插入)
db.students.save({"_id":ObjectId("1232kj23lkjlk43"), "age":50}) //按照_id更新,将age更新为50


修改器
$inc :将主要针对于一个数字字段,增加某个数字字段的数据内容
语法: {"$inc":{"成员":内容}}
db.students.update({"age":19, {"$inc": {"score":-30, "age":1}}}) 将所有年龄为19岁的学生,成绩减少30分,年龄加1岁  (默认只改一条,加 ,false,true 改所有)
$set :进行内容的重新设置
语法:{"$set":{"成员":""}}
db.students.update({"age":20}, {"$set":{"score":89}})  将年龄为20岁的学生,成绩设置成89分
$unset: 删除某个成员的内容
db.students.update({"name":"张三"},{"$unset": {"age":1, "score":1}}) //将name为张三的学生,age和score两个成员删掉(不是只是删掉内容)
$push: 相当于将内容追加到指定的成员之中(基本上是数组)
语法:${"$push": {成员 : value}}  ,增加的是数组,一次追加一个value
db.students.update({"name":"张三"},{$push :{"course": "语文"}})  //向张三添加课程信息,course字段是个数组
$pushAll  与$push类似,一次可增加多个value
db.students.update({"name":"张三"},{$pushAll :{"course": ["语文","美术"]}}) ;
$addToSet :向数组里面增加一个新的内容,只有这个内容不存在的时候才会增加
语法:{"$addToSet": {成员:内容}}
db.students.update({"name":"张三"},{$addToSet :{"course": "跳舞"}}) ; //会判断要增加的内容在数组中是否已经存在了,如果不存在则增加,存在则不增加。
$pop 删除数组内的数据
语法:{"$pop":{成员: 内容}}  ‘内容’设置成-1表示删除数组中第一个,‘内容’ 为1则删除数组中最后一个
db.students.update({"name":"王五"},{"$pop":{"course":-1}}) // 删除王五课程中第一门课
$pull 冲数组中删除只能内容的数据
语法:{"$pull":{成员:数据}}
db.students.update({"name":"王五"},{"$pull":{"course":"音乐"}}) // 删除王五课程中 音乐这门课
$pullAll :一次删除多个内容
语法: {"$pullAll":{成员:[数据,数据,..]}}
db.students.update({"name":"王五"},{"$pullAll":{"course":["音乐","数学"]}}) // 删除王五课程中 音乐、数学 这门课
$rename :为成员名称 重命名
语法:{"$rename":{旧成员名称: 新成员名称}}
db.students.update({"name":"张三"},{"$rename":{"name":"姓名"}})  //将张三的字段名‘name’ 改成 ‘姓名’,其他人不变


删除数据
remove()
db.infos.remove({});清空infos内的数据
db.students.remove({"name": /谷/})  //删除name中带有 谷的数据
db.students.remove({"name": /谷/},true)  //删除name中带有 谷的数据,只删除一个


游标(重点)
数据可以一行一行操作,非常类似于resultSet数据处理
hasNext() 判断是否有下一条数据
var curser = db.students.find();
curser.hasNext(); //返回true
curser.next(); //返回内容
while(curser.hasNext()){
var doc = curser.next();
print(doc.name);
printjson(doc); //打印所有数据
}


索引(重点)
自动创建的,手动创建
db.students.getIndexes(); 查询所有存在的索引
显示:{
"v" : 1,  
"key" : {"_id" : 1}, //1表示升序排序
"name" : "_id_",
"ns" : "mldn.students"
}
索引创建: db.集合名称.ensureIndex({列 : 1})
   1表示索引按照升序的方式进行排序,如果使用降序设置‘-1’。
db.students.ensureIndex({"age" : -1}) ; 在age上设置一个降序索引
   自动设置索引名称 “字段名称 + 排序类型 = age_-1”
db.students.find({"age" : 19}).explain(); //返回索引的操作分析
"stage" : "COLLSCAN"  //COLLSCAN集合扫描,相当于全表扫描
"stage" : "IXSCAN" //索引扫描
db.students.ensureIndex({"age" : -1, "score":-1},{name:"age-1_score-1_ind"}) ;
db.students.find({"age":19 , "score":89}).explain();
"stage" : "KEEP_MUTATIONS"
"stage" : "IXSCAN"
db.students.find({"$or": [{"age": {$gt:19}} ,{"score": {$gt:60}}]}).hint({"age":-1 , "score":-1})  //hint强制使用索引,一般$or不会使用索引,需要hint
删除索引:dropIndex()
db.students.dropIndex({"age":-1 , "score":-1});
删除全部索引:指的是非"_id"的索引,所有自定义的索引
dropIndexs()
db.students.dropIndexs();


唯一索引:使该字段的内容不重复。
db.students.ensureIndex({"name":1}, {"unique":true});


过期索引 :如手机验证码,这个时间往往不怎么准确
db.phones.insert({"tel":"110", "code":"111", "time": new Date()});
db.students.ensureIndex({"time":1}, {expireAfterSeconds:10}) //过期索引,在10秒后过期,10秒后(时间不准)所保存的数据就会消失


全文索引:
db.news.ensureIndex({"title":"text", "content":"text"}); //设置全文索引,字段title、content 为全文索引
db.news.ensureIndex({"$**":"text"}); //为所有字段设置全文检索,尽可能别用 因为慢。
    如果要想表示出全文索引,则使用 "$text"判断符,
    而想要进行数据查询,则使用  "$search"
查询指定关键字:{"$search":"查询关键字"}
查询多个关键字(或关系):{"$search":"查询关键字 查询关键字  查询关键字 .."}
查询多个关键字(与关系):{"$search":"\"查询关键字\" \"查询关键字\" ..."};  //  ‘\’是转义符  先"" 再"\"\""   再"\"查询关键字\" "
查询多个关键字(排除某一个):{"$search":"查询关键字 查询关键字 ...-"}  //最后有一个‘-’号
db.news.find({"$text":{"$search":"ggg"}}); //查询包含‘ggg’的数据,只对设置了全文检索的字段查找。
db.news.find({"$text":{"$search":"ggg aaa"}});//包含‘ggg’或‘aaa’的数据
db.news.find({"$text":{"$search":"\"mldn\" \"ggg\""}});  //包含有‘mldn’和‘ggg’ 的数据
db.news.find({"$text":{"$search":"\"mldn\" \"ggg\" -aaa"}});//包含‘mldn’和‘ggg’ 但是不包含‘aaa’的数据
db.news.find({"$text":{"$search":"ggg"}}, {"score":{"$meta":"testScore"}}); //$meta 查询的准确度 值越大越准确
db.news.find({"$text":{"$search":"ggg"}}, {"score":{"$meta":"testScore"}}).sort({"score":{"$meta":"testScore"}}); //按准确率排序,降序


地理信息索引
地理信息索引分为2类:2D平面索引、2DSphere球面索引
2D保存的都是经纬度坐标
db.shop.ensureIndex({"loc":"2d"}); //给loc字段建立2d索引,
对loc进行坐标位置查询:
"$near" 查询,查询距离某点最近的坐标点。
"$geoWithin"查询,查询某个形状的点。
db.shop.find({loc:{"$near":[11,11]}}) //查找里11,11近的坐标,距离100个点内的数据返回回来。
db.shop.find({loc:{"$near":[11,11], "$maxDistance":5}}) ;设置查询范围,距离5个点内的数据返回回来。
在2D索引里面支持最大距离,但是不支持最小距离。
但是可以设置一个查询范围,使用"$geoWithin"查询,可以设置的范围包括:
   矩形范围($box):{"$box":[[x1,y1],[x2,y2]]};
   圆形范围($center):{"$center":[[x1,y1],r]};
   多边形($polygon):{"$polygon":[[x1,y1],[x2,y2][x3,y3],...]}
db.shop.find({loc:{"$geoWithin":{"$box":[[9,9],[11,11]]}}}) ;//查询矩形
db.shop.find({loc:{"$geoWithin":{"$center":[[10,10],2]}}}) ;//查询圆形


runCommand() :可以执行所有的特定的MongonDB命令
db.runCommand({"geoNear":"shop",near:[10,10],maxDistance:5,num:2}); //针对shop集合 操作,10,10附近的,maxDistance:5:表示距离5个点内的数据,  num:2:表示返回的信息量2条
    "nscanned" : 17  //扫描了17条数据
"avgDistance" : 0.5 //平均距离是0.5
"maxDistance" : 1  //最大距离是1
"time" : 5  //花费时间5号秒


聚合(重点)
MongoDB产生背景是打数据背景下,统计操作就称为聚合。
db.students.count(); //统计行数
db.students.count({"name":/张/i}); 查询姓张的人 个数,不设置条件快很多


消除重复数据 distinct
操作没有直接的函数支持,只能利用runCommand进行。
db.runCommand({"distinct":"students", "key":"name"}); //只显示了name字段,对students表做distinct操作,查询name字段
显示"n":9  //去重复前的记录数
    "nscanned":0 ,
    "nscannedObjects":9 ,//扫描对象数,越少越好
    "timems":0 ,
    "planSummary":"COLLSCAN"


group操作
db.runCommand({"group": {"ns":"students", //集合名称students
"ksy":{"age":true},//按age分组
"initial":{"count":0}, //count初始化为0
"condition":{"age":{"$gte":19}},//筛选条件,age大于19
"$reduce":function(doc,prev){ print("doc="+ doc +"prev="+prev)} //
}});
map是处理操作,筛选
reduce是真正统计操作


MapReduce,就是分为两步去做
  Map:将数据区别取出
  Reduce:负责数据的最后处理
要在MongoDB里实现MapReduce处理,复杂度相当高
db.emps.insert({"name":"张三", "age":30, "sex":"男", "job":"clerk", "salary":8000}); 
var jobMapFun = function(){
emit(this.job,this.name); //按照job分组,取出name
}
var jobReduceFun = function(key,values){
return {"job":key, "names":values}; //key、values是个变量
}
var jobFinalizeFun(key,values){
if(key == "PRESIDENT"){
return {"job":key, "names":values, "info":"公司老大"}
}
retrun {"job":key, "name":values};
}
db.runCommand({
"mapreduce":"emps", //指定处理的表emps
"map":jobMapFun, //指定map方法jobMapFun
"reduce":jobReduceFun,
"out","t_job_emp" , //指定输出表名 t_job_emp
"finalize":jobFinalizeFun
})
db.t_job_emp.find();


统计出各性别的人数、平均工资、最低工资、雇员数:
var sexMapFun = function(){
emit(this.sex,{"ccount":1, "csal":this.salary, "cmax":this.salary, "cmin":this.salary}); //定义好分组的条件this.sex, 定义每个集合需要取出的内容
};
var sexReduceFun = function(key,values){
var total = 0; //统计
var sum = 0; //计算工资
var max = values[0].cmax; //假设第一个数据是最高工资
var min = values[0].cmin; //假设第一个数据是最低工资
var names = new Array(); //定义数组内容
for(var x in values){ //表示循环取出里面的数据
total += values[x].ccount; //人数增加
sum += values[x].csal; //可以循环取出所有的工资,并累加
if(max < valuesp[x].cmax){ //不是最高工资
max = values[x].cmax;
}
if(min > values[x].cmin){ //不是最低工资
min = values[x].cmin;
}
}
var avg = (sum/total).toFixed(2);
//返回处理结果
return {"count":total, "avg":avg, "sum":sum, "sin":sin};
}
db.runCommand({
"mapreduce":"emps" //指定集合名称emps
"map":sexMapfun,
"reduce":sexReduceFun,
"out":"t_sex_emp"
});
db.t_sex_emp.find();  //大数据时代提供MapReduct支持,但是现实中不可能使用。MapReduct超级费时


聚合框架(核心)
MapReduct功能强大,但是复杂度和功能一样强大,那么很多时候我们需要MapReduct的功能,可以是又不想把代码写的太复杂,
所以从Mongo2.x版本之后开始引入了聚合框架,并且提供了聚合函数:aggregate()


group  分组操作
取出每个职位的员工数:
db.emps.aggregate([{"$group":{"_id":"$job", job_count:{"$sum":1}}}]) //使用job列作为id列(用job分组) , job_count员工数
求出每个职位的总工资:
db.emps.aggregate([{"$group":{"_id":"$job", job_sal:{"$sum":"$salary"}}}]) //对salary列作sum计算
计算出每个职位的平均工资:
db.emps.aggregate([{"$group":{
"_id":"$job", //用job分组
"job_sal":{"$sum":"$salary"}, //对salary列作sum计算
"job_avg":{"$avg":"$salary"},// 对salary列作avg计算
"job_max":{"$max":"$salary"},
"job_min":{"$min":"$salary"} }}]); 


db.emps.aggregate([{"$group":{
"_id":"$job", //job分组
"sal_data":{"$push": "$name"} }}]); // 把每个职位的name放到数组里显示(没有去重复)
取消重复数据"$addToSet"
db.emps.aggregate([{"$group":{
"_id":"$job", //job分组
"sal_data":{"$addToSet": "$name"} }}]);// 把每个职位的name放到数组里显示(去重复)
保留第一个数据
db.emps.aggregate([{"$group":{
"_id":"$job", //job分组
"sal_data":{"$first": "$name"} }}]);// 分组后只保留第一个name
保存最后一个数据
db.emps.aggregate([{"$group":{
"_id":"$job", //job分组
"sal_data":{"$last": "$name"} }}]);// 分组后只保留最后一个name


所有数据都是无序的,都是在内存中完成的,所以不能支持大数据量。


$project
可以利用"$project"来控制数据列的显示规则,那么可以执行的规则如下:
    普通列({成员 : 1|true})  表示要显示的内容
    "_id"列({"_id":0|false})  表示"_id"列是否显示
    条件过滤列({成员 : 表达式})  满足表示之后的数据可以进行显示
只显示name、job列,不显示"_id"
db.emps.aggregate([{"$project":{"_id":0, "name":1}}]); //_id不显示,name显示, 属于数据库的投影机制
加法("$add")减法("$subtract"),乘法("$multiply"),除法("$divide")求模("$mod")
四则运算
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"职位":"$job", //显示job列,取别名"职位"
"salary":1 }}])

db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"job":1,
"salary":{"年薪":{"$multiply":["$salary",12]}} }}]); //计算年薪 = salary * 12
关系运算:大小比较("$cmp")、等于("$eq")、大于("$gt")、大于等于("$gte")、小于等于("$lte")、不等于("$ne")、判断null("$ifNull"),返回逻辑型数据
逻辑运算:与("$and")、或("$or")、非("$nor")
字符串操作:连接("$concat")、截取("$substr")、转小写("$toLower")、转大写("$toUpper")、大小写比较("$strcasecmp")
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"job":1,
"工资":"$salary", //要想显示工资列,需要使用别名
"salary":{"$gte":["$salary",2000]} }}]); //salary显示的是是否符合查询  true|false如下
显示:
{"name":"张三", "job":"CLERK", "salary":false, "工资":1000}  
{"name":"李四", "job":"CLERK", "salary":true, "工资":5000}  
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"职位":"$job", 
"job":{"$eq":["$job",{"$toUpper":"manager"}]} }}]); //将job转换成大写
显示:
{"name":"张三", "job":false, "职位":"CLERK" }  
{"name":"李四", "job":true, "职位":"MANAGER"  }  
MongoDB中的数据是区分大小写的。
db.emps.aggregate([{"$project":{
"_id":0,
"name":1,
"职位":"$job", 
"job":{"$strcasecmp":["$job","manager"]} }}]);
显示:
{"name":"张三", "job":-1, "职位":"CLERK" }  //小于为-1 等于为0 大于为1
{"name":"李四", "job":0, "职位":"MANAGER"  }  


聚合框架($sort)
1表示升序,-1表示降序
db.emps.aggregate([{"$sort: {"age":-1, "salary":1}"}])
db.emps.aggregate([
{"$match":{"salary":{"$gte":1000,"$lte":10000}}}, //做match计算
{"$project":{"$_id":0, "name":1, "salary":1, "job":1}},  //控制显示规则 0为不显示 1为显示
{"$group":{"_id":"$job", "count":{"$sum":1}, "avg":{"$avg":"$salary"}}}, //用job分组
{"$sort":{"count":-1}} //做排序,用上一行的“count”别名
]);


分页处理 $limit、$skip
$limit:负责数据的取出个数
$skip:数据的跨过个数
db.emps.aggregate([
{"$project":{"_id":0, "name":1, "salary":1, "job":1}}, //第一行
{"$skip":3}, //先跨过3行数据 //第二行
{"$limit": 2}//取2行数据 //第三行
]);  //执行顺序是:先第一行,再执行第二行,再执行第三行,所以第二行和第三行不能写反了。


"$unwind"
查询数据段 时候返回数组信息,但是数组不方便信息的浏览,所以提供有$unwind,可以将数组信息变为独立的字符串内容。
db.depts.aggregate([
{"$project":{"_id":0, "title":1, "bus":1}},
{"$unwind":"$bus"}]);  //相当于把数组中的数据变为但行的数据


$geoNear
使用$geoNear可以得到附近的坐标点,必须有2d索引的支持
db.shop.insert({loc:[10,10]});
db.shop.insert({loc:[12,13]});
db.shop.insert({loc:[30,50]});
db.shop.ensureIndex({"loc":"2d"}); //2d索引
db.depts.aggregate([
{"$geoNear":{"near":[11,12],   //在什么附近
"distanceField":"loc",  //设置坐标点字段
"maxDistance":1, //最远的距离
"num":2, //返回2条记录
"spherical":true}} //设置球面的方式
])


$out
利用此操作可以将查询结果输出到指定的结合里面
将投影的结果输出到集合里,会新建一个新表emp_infos ,实现了表的复制操作:
db.emps.aggregate([
{"$project":{"_id":0, "name":1, "salary":1, "job":1}},
{"$out":"emp_infos"}
])


固定集合
规定集合大小,如果要保存的内容已经超过了集合的长度,那么会采用lru的算法(最近最少使用原则)将最早的数据移出,从而保存新的数据
默认使用createCollection()函数创建,或者使用增加数据后自动创建,要使用固定集合,必须明确创建一个空集合。
创建空结合(固定集合):
db.createCollection("depts",{"capped":true, //表示有容量限制的
"size":1024,   //集合的容量,最多1024字节
"max":5});     //最多有5行记录
元外之元--阿拉伯数字


GridFS
MongoDB里面处置大数据的存储 如:图片,音乐,各种二进制
使用mongFiles命令完成
1.利用命令行进入文件所在目录
2.将文件保存到文件库中:
d:> mongfiles --port=27001 put photo.tif
3.查看保存的文件
d:> mongfiles --port=27001 list
4.在MongoDB里面有一个fs系统集合,这个集合默认保存在了test集合下
show dbs;//显示了每个db的大小
use tset;
show collections; //显示所有的集合
db.fs.files.find();//fs是系统集合,显示刚才保存进来的photo.tif文件
5.删除文件
d:>mongofiles --port=27001 delete photo.tif


用户管理
在mongoDD里面默认情况下只要是进行连接都可以不使用用户名和密码,必须符合以下几个条件
 条件1.服务器启动的时候打开授权认证
 条件2.需要配置用户名和密码
 想要配置用户名和密码一定是针对于一个数据库的,
   必须先切换到mldn数据库上:use mldn
   任何用户都具备一个自己的操作角色,对于角色最近处的角色:read、readWrited、
db.createUser({
  "user":"hello",  //创建用户hello
  "pwd":"java",
  "roles":[{"role":"readWrite", "db":"mldn"}]
  })
以授权的方式打开MongoDB
mongodb.conf配置文件增加如下配置
auth = true    //验证的启动模式
此时增加了一个验证的启动模式,发现依然可以不输入用户和密码进行登录,并且也可以直接进行数据库的切换操作。
但是在使用数据库集合的时候出现了错误的提示。
登录数据库使用 用户名和密码:
mongo localhost:27001/mldn -u hello -p java  //登录数据库mldn
如果要改密码,那么就请关闭授权登录,需要noauth=true
db.changeUserPassword("hello","happy"); //修改密码


java 连接MongoBD操作 (基于2.x驱动),MongoDB只做这些操作如下1,2,3,4,5
MongoDB实际上是作为一个附属数据库存在,只有Node.js把他作为正室,除了Node.js之外,是个不能够单独使用的数据库,都需要与传统关系型数据库匹配使用。
public class MongoDemoA{
public static void main(){ //1111
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");//连接数据库
if(db.authenticate("hello","happy".toCharArry())){ //进行数据库的用户名密码验证
DBCollection col = db.getCollection("deptcol");//要操作的集合名字,表名
for(int x=0;x<100 ;x++){
BasicDBObject obj = new BasicDBObject();
obj.append("deptno",1000+x);
obj.append("dname","技术部-"+x);
obj.append("loc","北京-"+x);
col.insert(obj); //保存数据
}
}
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");
DBCursor cursor= col.find().skip(0).limit(10); //得到分页信息
while(cursor.hasNext()){
DBObject obj = cursor.next();
System.out.println("部门编号:"+ obj.get("deptno")+ "名称"+obj.get("dname"));
}
}
client.close();
///
}
}
public static void main(){//2222222  大于、小于、in 查询
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");//连接数据库
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//设置表名
//BasicDBObject存放where条件,或者存放查询后的数据
DBObject cond = new BasicDBObject();//准备设置查询过滤
//只要有json格式都是用new BasicDBObject,如下
cond.put("deptno",new BasicDBObject("$gte",1000).append("$lte",1020));//设置deptno的数据范围在1000 --1020之间
//cond.put("deptno",new BasicDBObject("$in",new int[]{1001,1003,1005}));//in操作
//设置查询条件 如下
DBCursor cursor = col.find(cond).skip(0).limit(50); //得到全部内容
while(cursor.hasNext()){
DBObject obj = cursor.next();
System.out.println("部门编号:"+ obj.get("deptno")+ "名称"+obj.get("dname"));
}
}
client.close();
}
public static void main(){//3333  模糊查询
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//设置表名
//Pattern正则的编译 没有构造方法,
Pattern pattern = Pattern.complie("5");//设置过滤条件,类似 like %5%
DBObject cond = new BasicDBObject();//BasicDBObject存放where条件,或者存放查询后的数据

cond.put("dname",new BasicDBObject("$regex",pattern));//只要有json格式都是用new BasicDBObject
//设置查询条件 如下
DBCursor cursor = col.find(cond).skip(0).limit(50);
while(cursor.hasNext()){
DBObject obj = cursor.next();
System.out.println("部门编号:"+ obj.get("deptno")+ "名称"+obj.get("dname"));
}
}
client.close();
}
public static void main(){//44444  数据修改
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//设置表名
DBObject condA = new BasicDBObject();//BasicDBObject存放where条件,或者存放查询后的数据,或json格式条件
condA.put("deptno",1000); //设置修改内容,deptno=1000
//condA.put("deptno",new BasicDBObject("$gte",1000).append("$lte",1020));
DBObject condB = new BasicDBObject();
condB.put("$set",new BasicDBObject("dname","修改后的内容")); //修改后的内容
WriteResult result = col.update(condA,condB);//执行更新,A更新为B
//WriteResult result = col.updateMulti(condA,condB);//修改多行 用 updateMulti
System.out.pirntln(result.getN()); //getN表示更新到的行数,存在则更新,不存在则新增。
}
client.close();
}
public static void main(){//55555  删除数据
MongoClient client = new MongoClient("localhost",270001);
DB db = client.getDB("mldn");
if(db.authenticate("hello","happy".toCharArry())){
DBCollection col = db.getCollection("deptcol");//设置表名
DBObject cond = new BasicDBObject();//BasicDBObject存放where条件,或者存放查询后的数据,或json格式条件
cond.put("deptno",new BasicDBObject("$gte",1000).append("$lte",1020));
WriteResult result = col.remove(cond);//执行删除
System.out.pirntln(result.getN()); //getN表示更新到的行数
}
client.close();
}
java 连接MongoBD操作 (基于3.x驱动)
public class Mongo3DemoA{ //1111
public static void main(){ 
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用户名密码hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
//System.out.println(db.getCollection("deptcol").count());//获取表deptcol集合
MongoCollection col = db.getCollection("stucol");
List<Document> all = new ArrayList<Document>();
for(int x=0 ; x<100 ; x++){
Document doc = new Document();
doc.append("sid",x);
doc.appent("name","姓名-"+x);
all.add(doc);
}
col.insertMany(all);
client.close();
}
}
public static void main(){ //22222 查询
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用户名密码hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
DBObject cond = new BasicDBObjcet();
cond.put("sid",new BasicDBObject("$gt",5).append("$lt",20));
MongoCursor<Document> cursor = col.find(cond).skip(5).limit(10).iterator();//跳过5,取10个
while(cursor.hasNest()){
System.out.println(cursor.next());
}
client.close();
}
public static void main(){ //33333 模糊查询
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用户名密码hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
Pattern pattern = Pattern.compile("10"); //like %10%
DBObject cond = new BasicDBObjcet();
cond.put("name",new BasicDBObject("$regex",pattern).append("$options","1")); //options 1不区分大小写
MongoCursor<Document> cursor = col.find(cond).iterator();
while(cursor.hasNest()){
System.out.println(cursor.next());
}
client.close();
}
public static void main(){ //44444 数据更新
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用户名密码hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
BasicDBObject condA = new BasicDBObject("sid",0);//数据查询条件
BasicDBObject condA = new BasicDBObject("$set",new BasicDBObject("name","超人"));
UpdateResult result = col.updateMany(condA,condB);
System.out.pirntln(result.getMatchedCount());//取得 修改条数
client.close();
}
public static void main(){ //55555 数据删除
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用户名密码hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
MongoCollection col = db.getCollection("stucol");
BasicDBObject cond = new BasicDBObject("sid",0);//数据查询条件 sid=0
DeleteResult result = new col.deleteOne();
System.out.pirntln(result.getDeletedCount());//取得 修改条数
client.close();
}
public static void main(){ //666666 统计查询
MongoClientURI uri = new MongoClientURI("mongodb://hello:happy@localhost:27001/mldn");//用户名密码hello:happy
MongoClient client = new MongoClient(uri);
MongoDatabase db = client.getDatabase("mldn");
List<BasicDBObject> all = new ArrayList<BasicDBObject>();
MongoCollection col = db.getCollection("stucol");
BasicDBObject cond = new BasicDBObject(
"$group",new BasicDBObject("_id","$sex")
.append("count",new BasicDBObject("$sum",1))
.append("avg",new BasicDBObject("%avg","%salary")));//
all.add(cond);
MongoCursor<Document> cursor = col.aggregate(all).iterator();
while(cursor.hasNext()){
Cocument doc = cursor.next();
System.out.println(doc.getString("_id")+","+ doc.getInteger("count") +","+ doc.getDouble("avg"));
}
client.close();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值