mongoDB入门:
mongoDB常用于前端数据加速读写,提升用户体验,且不涉及原子复杂事务,或者用于表字段不确定的场景,主要针对一些廉价数据。
BSON : JSON扩展,增加了新的数据类型,而且能转成二进制码存储;
mongoDB 表: 集合list ; 表的一行数据(对象{}) : 文档document;
mongoDB查询使用内置的find函数,基于BSON的特殊查询工具;
基本操作:
1,创建一个数据库: use [databaseName] 但是你什么也不干就离开的话这个空数据库就会被删除;
2,查看所有数据库: show dbs
3,给指定数据库添加集合并且添加记录: db.[documentName].insert({…})
4,查看数据库中的所有文档: show collections
5,查询指定文档的数据: 查询所有: db.[documentName].find()
查询第一条数据 db.[documentName].findOne()
6,更新文档数据: db.[documentName].update({查询条件},{更新内容})
eg: var p = db.persons.findOne()
db.persons.update(p,{name:”uspcat”})
7,删除文档中的数据: egg: db.persons.remove({name:”uspcat”})
8,删除库中的集合: db.[documentName].drop()
9,删除数据库: db.dropDatabase()
10,Shell的help: 里面所有的shell可以完成的命令帮助,全局的help 数据库相关的db.help() 集合相关的db.[documentName].help()
数据库和集合命名规范: 1,不能为空字符串 2,不得含有’ ’(空格)、,、$、/、\和\o(空字符) 3,应全部小写 4,最多64个字节 5,数据库名不能与现有系统保留库同名,如admin,local及config
mongoDB的shell内置javascript引擎;
批量插入文档:shell这样执行是错误的 db.[documentname].insert([{},{},{}..])
shell不支持批量插入,但可以用shell的for循环实现;
Save操作:save操作和insert操作区别在于遇到_id相同的情况下,save会更新相应记录,insert则会报错主键冲突;
修改器放在外层,查询器放到内层;
$addToSet与$each结合完成批量数组更新: db.text.update({_id:1000},{$addToSet:{books:{$each:[“JS”,”DB”]}}}) $each会循环后面的数组把每一个数值进行$addToSet操作
runCommand函数和findAndModify函数:runCommand可以执行mongoDB中的特殊函数,findAndModify就是特殊函数之一,用于返回update或remove后的文档;
find详解:
查询条件: eg: 查询出年龄在25到27之间的学生
db.persons.find({age:{$gte:25,$lte:27},{_id:0,age:1})
包含或不包含($in或$nin): eg: 查询国籍不是中国或者美国的学生:
db.person.find({country:{$nin:[“USA”,”China”]}})
OR查询($or): eg: 查询语文成绩大于85或者英语大于90的学生信息
db.persons.find({$or:[{c:{$gte:85}},{e:{$gte:90}}]},{_id:0,c:1,e:1})
Null: eg: 把中国籍的学生上加上新的键sex
db.persons.update({country:”China”},{$set:{sex:”m”}})
接着查询出sex等于null的学生
db.persons.find({sex:{$in:[null]}},{country:1})
正则查询: eg: 查询名字中存在“li”的学生的信息
db.persons.find({name:/li/i},{_id:0,name:1})
$not的使用: eg: 查询出名字中不存在”li”的学生的信息
db.persons.find(name:{$not:/li/i}},{_id:0,name:1})
$not和nin的区别是$not可以用在任何地方而$nin只用在集合上
数组查询$all和index应用: eg: 查询喜欢看mogoDB和JS的学生
db.persons.find({books:{$all:[“mongoDB”,”JS”]}},{books:1,_id:0})
eg: 查询第二本书是java的学生信息
db.persons.find({“books.1”:”java”})
综合案例: 查询出喜欢的书籍数量大于3本的学生
1,增加字段size: db.persons.update({},{$set:{size:4}},false,true)
2,改变书籍的更新方式,每次增加书籍的时候size增加1
db.persons.update({查询器},{$push:{books:”Oracle”},$inc:{size:1}})
3,利用$gt查询 db.persons.find({size:{$gt:3}})
综合案例: 利用shell查询出Jim喜欢看的书的数量
var persons = db.persons.find({name:”jim”})
while(persons.hasNext()){
obj = persons.next();
print(obj.books.length)
}
$slice操作符返回文档中指定数组的内部值: eg: 查询jim书架中第2~4本书
db.persons.find({name:”jim”},{books:{“$slice”:[1,3]}})
eg: 查询出最后一本书:
db.persons.find({name:”jim”},{{books:“$slice”:-1},_id:0,name:1})
单个条件组查询$elemMatch: eg: 查询在K学校上学且成绩为A的学生
db.persons.find({school:{$elemMatch:{school:”K”,score:”A"}}})
万能查询$where(性能下降): eg:查询年龄>22岁,爱看C++,在K学校上过学的学生
db.persons.find({“$where”:function(){
var books = this.books;
var school = this.school;
if(this.age >22){
var favorite = null;
for(var i = 0; i < books.length;i++){
if(books[i] == “C++”){
favorite = books[i];
if(school){
for(var j = 0;j < school.length;j++){
if(school[j].school == “K”){
return true;
}}
break;
}}}}
}})
分页与排序:
Limit返回指定的数据条数: eg: 查询出persons文档中前5条数据
db.persons.find({},{_id:0,name:1}).limt(5)
Skip返回指定数据的跨度: eg: 查询persons文档中5~10条数据
db.persons.find({},{_id:0,name:1}).limit(5).skip(5)
Sort返回按照年龄排序数据[1,-1]: db.persons.find({},{_id:0,name:1,age:1}).sort({age:1})
注意:mongoDB的key可以存不同类型的数据,排序也就有优先级
性能优化: 每次查询操作的时候前后台传值把上次的最后一个文档的日期保存下来
db.persons.find({date:{$gt:日期数值}}).limit(3)
避免用skip带来性能损耗
游标: 利用游标遍历查询数据
var persons = db.persons.find();
while(persons.hasNext()){
obj = persons.next();
print(obj.name);
}
游标的销毁条件: 1,客户端发来信息叫它销毁 2,游标迭代完毕 3,默认游标超过10分钟没用也会被清除
查询快照: 快照后就会针对不变的集合进行游标运行了,
使用方法示例: db.persons.find({$query:{name:”Jim”},$snapshot:true})
索引:
创建简单的索引: eg: 为number创建索引,db.books.ensureIndex({number:1})
索引使用需要注意的地方:1、创建索引的时候,1正序,-1倒序 2、索引的创建提高查询性能但影响插入性能,对于经常查询且很少插入的文档可以考虑用索引 3、符合索引要注意索引的先后顺序 4、每个键建立索引不一定能提高性能 5、在做排序工作的时候,如果是超大数据量也可以考虑加索引来提高排序的性能
system.indexes: eg: 在shell查看数据库已经建立的索引
db.system.indexes.find()
db.system.namespaces.find()
后台执行: 执行创建索引的过程会暂时锁表,该问题如何解决
db.books.ensureIndex({name:-1},{background:true})
删除索引: 批量删除: db.runCommand({dropIndexes:”books”,index:”*”})
精确删除: db.runCommand({dropIndexes:”books”,index:”name_-1”})
mongoDB提供强大的空间索引可以查询出一定范围内的地理坐标:
eg: 查询距离点(70,180)最近的三个点:
添加2d索引:db.map.ensureIndex({“gis”:”2d”},{min:-1,max:201})
默认会建立一个一个[-180,180]之间的2d索引,
db.map.find({“gis”:{$near:[70,180]}},{gis:1,_id:0}).limit(3)
eg: 查询以点(50,50)和点(190,190)为对角线的正方形中的所有点
db.map.find({gis:{$within:{$box:[50,50],[190,190]}}},{_id:0,gis:1})
eg: 查询以(56,80)为圆点,半径为50的圆面中的点
db.map.find({gis:{$within:{$center:[[56,80],50]}}},{_id:0,gis:1})
聚合操作:
Count: eg: 查询persons中美国学生的人数
db.persons.find({country:”USA”}).count()
Distinct: eg: 查询出persons中一共有多少个国家分别是什么
db.runCommand({distinct:”persons”,key:”country”}).values
Group: 语法: db.runCommand({group:{
ns:集合名字, Key:分组的键对象, Initial:初始化累加器, $reduce:组分解器,
Condition:条件, Finalize:组完成器 }})
分组首先按照key进行分组,每组的每一个文档全要执行$reduce的方法
eg: 查询persons中每个国家学生数学成绩最好的学生信息(必须在90以上),并在结果后面追加描述信息
db.runCommand({group:{ns:”persons”,key:{“country”:true},initial:{m:0},
$reduce:function(doc,prev){
if(doc.m > prev.m){
prev.m = doc.m;
prev..name = doc.name;
prev.country = doc.country;
},
finalize:function(prev){
prev.m = prev.name+” Math scores “+prev.m
},
condition:{m:{$gt:90}}
}}})
固定集合:
特性:1、默认没有索引就算是_id也没有索引 2、由于不需分配新的空间所以插入速度很快 3、顺序确定所以查询速度很快 4,最适合日志管理
创建固定集合:eg: 创建一个新的固定集合,要求大小100个字节,可以存储10个文档
db.createCollection(“mycoll”,{size:100,capped:true,max:10})
eg: 把一个普通集合转换成固定集合
db.runCommand({convertToCapped:”persons”,size:100000})
反向排序,默认是插入顺序排序: eg: 查询固定集合mycoll并且反向排序
db.mycoll.find().sort($natural:-1)
尾部游标:可惜shell不支持,但java和php等驱动支持
尾部游标概念:这是个特殊的只能用在固定集合身上的游标,它在没有结果的时候也不会自动销毁,并一直等待结果的到来;
GridFS:是mongoDB自带的文件系统,它用二进制的形式存储文件,大型文件系统的绝大多数特性GridFS都可以完成;
mongoDB默认端口号:27017
Fsync锁: 上锁: db.runCommand({fsync:1,lock:1}) 解锁: db.currentOp()
数据修复:db.repairDatabase
添加一个用户: db.addUser(“uspcat”,”123”)
启动用户: db.auth(“名称”,“密码”)
安全检查: -auth
用户删除操作: db.system.users.remove({user:”king”})
高可用:主从复制,副本集
分片: 查看配置库对于分片服务器的配置: db.printShardingStatus()
查看集群对bar的自动分片机制配置信息: db.shards.find()
java操作mongoDB:
连接数据库:static Mongo connection = null;
static DB db = null;
public MongoDb(String dataBaseName) throws UnknownHostException,MongoException{
connection = new Mongo(“127.0.0.1:27017”);
db = connection.getDB(dataBaseName);
}
所有key-value的操作在java中以DBObject进行
批量插入,只需构建相应List<DBObject>
根据id删除时,要注意id是object类型,所以传参new Object(id)
批量按条件删除: public int deleteByDbs(DBObject find,String collName){
DBCollection coll = db.getCollection(collName);
return coll.remove(find).getN();
}
更新操作: DBObject update = new BasicDBObject();
update.put(“$set”,new BasicDBObject(“age”,1);
mongoDb.update(new BasicDBObject(),update,false,true,”javadb”);
//第一个参数:查询器,第二个参数:更新器,第三个参数:是否createOrUpdate,第四个参数:是否批量更新,第五个参数:集合名称