一、文档基本操作
目录:
1、Document数据插入
2、Document数据删除
3、Document数据更新
1、Document数据插入
1.1插入文档(insert)
db.[documentName].insert({})
1.2批量插入文档
shell不支持批量插入,db.[documentName].insert([{},{},{}…])是错误的。
想完成批量插入文档可以使用mongo的应用驱动或是shell的for循环。只有插入多个文档到一个集合时可以使用,不支持批量插入一次性对多个文档执行批量插入操作。
1.3save操作
等同于insert()操作,区别在于:如果插入的集合的“_id”值,在集合中已经存在,用Insert执行插入操作回报异常,已经存在”_id”的键。用Save如果系统中没有相同的”_id”就执行插入操作,有的话就执行覆盖掉原来的值,相当于修改操作。
2、Document数据删除
2.1删除列表中所有数据
db.[documentName].remove()
集合的本身和索引不会被删除。
2.2根据条件删除
db.[documentName].remove({})
例如:删除persons集合中name键等于”zhangsan”的记录,db.persons.remove({name:”zhangsan”})
2.3小技巧
如果想删除一个数据量十分庞大的集合,可以直接删除该集合(db.drop_collection(“documentName”))并且重新建立索引的方法,效率要比remove效率高很多。
3、Document数据更新
3.1强硬的文档替换式更新操作
db.[documentName].update({查询器},{修改器})
此更新方法会用新的文档代替老的文档,但是主键冲突时会报错并停止更新操作。
3.2使用修改器完成局部更新操作
通常文档只有一部分需要更新,此时可以考虑使用更新修改器($)。更新修改器是种特殊的键,用来指定复杂的更新操作,如调整、增加或删除,还可以操作数组或者内嵌文档。
注意:使用修改器时,”_id”的值不能改变。
3.3insertOrupdate操作
db.[documentName].update({查询器},{修改器},true)
此方法的目的是查出来数据就执行更新操作,查不出来就执行替换操作
3.4批量更新操作
db.[documentName].update({查询器},{修改器},false,true)
默认情况下当查询出来多天数据的时候就默认修改第一条数据,但是执行此方法可以显现批量修改。
3.5
addToSet与
each结合完成批量数组更新
db.persons.update({_id:1000},{$addToSet:{books:{$each:["JS","JAVA"]}}})
each会循环后面每一个数组吧每一个数组进行
addToSet操作。
3.6存在分配和查询效率
当document被创建时,DB为其分配了内存和预留内存,当修改操作不超过预留内存的时候查询效率非常快,当修改操作超过了预留内存时就要分配新的内存,此时就会比较耗费时间。
3.7runCommand函数和findAndModify函数
runCommand可以执行MongoDB中的特殊函数,findAndModify就是特殊函数之一,用于返回update或remove后的文档。举例略。
二、 Find查询
目录
1、Find详讲
2、分页和排序
3、游标和其他知识
1、Find详讲
db.[documentName].find({查询条件},{键指定})
查询所有数据的指定键(name,age,country): db.persons.find({},{name:1,age:1,country:1,_id}:0})
1.1查询条件
查询出年龄在25和27岁之间的学生
db.persons.find({age:{$gte:25,$lte:27}},{_id:0,age:1})
1.2包含和不包含
查询国籍是美国或中国的学生信息
db.persons.find({country:{$in:["China","USA"]}})
1.3or查询
查询英语成绩大于85或语文成绩大于90的学生信息
db.persons.find({$or:[{e:{$gte:85}},{c:{$gte:90}}]},{_id:0,c:1,e:1})
1.4null
把中国国籍的学生加上新的键”sex”
db.persons.update({country:"China"},{$set:{sex:"M"}},false,true)
查询出sex等于null的学生
db.persons.find({sex:{$in:[null]}},{_id:0,name:1,sex:1})
1.5正则查询
查询出名字中存在”li”的学生的信息
db.persons.find({name:/li/i},{_id:0,name:1})
1.6not的使用
与in不同处:not可以用到任何地方进行取反操作
查询出名字中不存在”li”的学生信息
db.persons.find({name:{$not:/li/i}},{name:1,_id:0})
1.7数组查询$all和index的查询
查询出喜欢看”MongoDB”和”JS”的学生的信息
db.persons.find({books:{$all:["MongoDB","JS"]}},{name:1,books:1,_id:0})
查询第二本书是”JS”的学生的信息
db.persons.find({"books.1":"JS"},{_id:0,name:1})
1.8查询指定长度数组$size,但它不能与比较查询运算符一起使用,这是弊端
查询出书籍数量大于4本的学生的信息
db.persons.find({books:{$size:4}},{_id:0,name:1})
1.9查询出喜欢的书籍数量大于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}})
1.10利用shell查询出Jim喜欢看的书的数量
var Jim = db.persons.find({name:"Jim"})
while(persons.hasNext())
{
obj = persons.next();
print(obj.books.length);
}
1.11$slice操作符返回文档中指定数组内部值
查询出Jim书架中第2-4本书
db.persons.find({name:"Jim"},{books:{$slice:[1,3]}})
查询出Jim书架中最后一本书
db.persons.find({name:"Jim"},{books:{$slice:-1}})
1.12文档查询
查询出在K学校上过学的学生
1)用绝对匹配可以完成,但是有问题(如顺序之类的)
db.persons.find({school:{school:"K",score:"A"}},{_id:0,name:1})
2)为了解决顺序问题我们可以使用”对象.”的方式定位
db.persons.find({"school.score":"A","school.school":"K"},{_id:0,name:1})
3)正确的解法:单条条件组查询$elemMatch
db.persons.find({school:{$elemMatch:{school:"K",score:"A"}}})
1.13where
当键/值对查询方式无法依然表达需求时,可是考虑使用”$where”万能字句,它可以执行任意JavaScript作为查询的一部分。该查询几乎能做任何事情。
举例略。
2、分页和排序
2.1 limit返回指定数据条数
查询出文档中前5条数据
db.persons.find({},{_id:0,name:1}).limit(5)
2.2skip返回指定数据的跨度
查询出文档中第5-10条数据
db.persons.find({},{_id:0,name:1}).limit(5).skip(5)
2.3sort返回按照年龄排序的数据[1,-1]
db.persons.find({},{_id:0,name:1,age:1}).sort({age:1})
注意:MongoDB中的key可以是不同类型的数据排序也就是优先级
排序顺序:最小值->null->数字(整数、长整型、双精度)->字符串->对象/文档->数组->二进制数据->对象ID->布尔型->日期型->时间戳->正则表达式->最大值
2.4limit和skip完成分页
三个数据为一页进行分页
第一页: db.persons.find({},{_id:0,name:1}).limit(3).skip(0)
第二页: db.persons.find({},{_id:0,name:1}).limit(3).skip(3)
但是使用skip进行分页时会有性能问题,当数据量非常大时,我们尝试使用date重构文档结构,即每次查询操作时,前台传值将上次最后一个文档的日期保存下来。
db.persons.find({date:{$gt:日期数值}}).limit(3)
个人建议:应该将软件的重点放在便捷和精确查询上而不是分页性能上,因为用户翻查最多不会2页。
3、游标和其他知识
3.1游标
利用游标遍历查询数据
var persons = db.persons.find();
while(persons.hasNext())
{
obj = persons.next();
print(obj.name);
}
persons.hasNext()检查是否有后续结果存在,然后用persons.next()将其获得。
3.2游标的几个销毁条件
1)客户端发来消息将其销毁;
2)游标迭代完毕;
3)默认游标超过10分钟没有用则会自动清除。
3.3查询快照
快照后就会针对不变的集合进行游标运动。所有返回一组结果的查询实际上都进行了快照,不一致只在游标等待结果时集合内容被改变的情况下发生。
db.persons.find({$query:{name:"Jim"},$snapshot:true})
3.4高级查询选项
$query
$orderby
$maxscan:integer //指定查询最多扫描的文档数量
$min:document //查询的开始条件
$max:document //查询的结束条件
$hint:document //指定服务器使用哪个索引进行查询
$explain:boolean //获取查询执行的细节(用到的索引、结果数量、耗时),而非真正执行查询
$snapshot:boolean //确保查询结果是在查询执行的那一刻的一致快照。
注意:
1、mongodb是Nosql数据库,它在文档查询上功能很强大;
2、查询符基本上放在花括号里面,更新符基本上放在花括号外面;
3、shell是个彻底的JS引擎,但是一些特殊的操作要靠它的各个驱动包来完成,如java,node.js