查询
1.db.c.find() :返回集合c中所有的内容
2.条件查询:
例子
1).要查询所有的"age"的值为27的文档
db.users.find({"age":27})
2).查询 "username"的值为joe 的文档
db.users.find({"username":"joe"})
3).查询age是27 且 username是joe的文档
db.users.find({"username":"joe","age":27})
3.返回指定的键值对(根据find()的第二个参数)
例子
1).查询用户集合的username 和 email
db.user.find({},{username:1,email:1})
注意点:
1:代表需要
0:代表不需要
_id这个键总是被返回
2). 查询用户集合的文档 不希望返回含有sex的键
db.user.find({},{"sex":0})
也可以防止生成_id
4.查询条件
1).$lt、$lte、$gt、$gte、$ne
<、<=、>、>=、不等于
例子:
1).查找2007年1月1日前注册的人
start = new Date("01/01/2007")
db.users.find({"age":{"$lt":start}})
2). 查询用户年龄在18-30的用户
db.users.find({"age":{"$gte":18,"$lte":30})
3).查询名字不是“joe”的用户
db.users.find({"username":{"$ne":"joe"}})
5.OR查询
1)$in
1)例子一
查找中奖号码 是 725或255或155 的所有号码编号
dao.raffle.find({"ticket_no":{"$in":[725,255,155]}})
2)例子二
可以是不同的类型
dao.users.find({"users":{"$in":["abc",1234]}})
2).$nin :与$in 相反
1).查询没中奖的用户
dao.raffle.find({"ticket_no":{"$nin":[725,255,155]}})
3).$or
1).dao.raffle.find({"$or":[{"ticket_no":{"$in":[725,255,155]}},{"winner":true}]})
4).$not
1).$mod
dao.find({"id_num":{"$mod":[5,1]}})
说明 $mod 会将查询的值 除以第一个数(5) 若余数等于第二个
则返回该数 该查询返回的结果是:1,6,11,16...
2)返回以上相反地结果
dao.find({"$id_num":{"$not":{"$mod":[5,1]}}})
6.条件语句的规则
1):条件句是内层文档的键、而修改器则是外层文档的键
2):可以对一个键应用多个条件
db.users.find({"age":{"$lt":30,"$gt":20}})
3):一个键不能有多个修改器
错误写法:{"$inc":{"age":1},"$set":{"age":40}}
7.null
它不但能够匹配自身 而且能匹配"不存在"
如果仅仅想要匹配键值为null的文档
db.c.find({"z":{"$in":[null],"$exists":true}})
8.正则表达式
正则表达式能够灵活有效的匹配字符串
例一
db.users.find({"name",/joe/i})
9.查询数组
db.food.insert({"fruit":["apple","banana","peach"]})
查询
db.food.find({"fruit":"banana"})
1).$all
db.food.insert({"_id":1,"fruit":["apple","banana","peach"]})
db.food.insert({"_id":2,"fruit":["apple","kumquat","orange"]})
db.food.insert({"_id":3,"fruit":["cherry","banana","apple"]})
db.food.find({"fruit":{$all:["apple","banana"]}})
db.food.find({"fruit":"apple"}) 等价于 db.food.find({"fruit":{$all:"apple"}})
精确匹配
db.food.find({"fruit":["apple","banana","peach"]})
2).$size
db.food.find({fruit:{$size:3}})
对于key来说 加引号和不加一个样(js规定的)
注意:$size 不能和其他的查询子句组合 例如 $gt
解决以上办法:可以采用以下技巧
db.food.insert({fruit:["orange","apple","peach"],size:3})
db.food.update({},{$push:{fruit:"banana"},$inc:{size:1}})
db.food.findOne({size:{$gt:3}})
这个技巧$addToSet 不能用
3).$slice
db.blog.findOne(criteria,{"comments":{$slice:10}}) 查询记录的前10条评论
db.blog.findOne(criteria,{"comments":{$slice:-10}}) 查询记录的末10条评论
db.blog.findOne(criteria,{"comments":{$slice:[23,10]}})
第24条开始 总数是10天 不足10条 就到末尾
4).查询内嵌文档
{
name:{
first:"joe",
last:"jamea"
},
age:45
}
正确写法:db.user.find({name:{first:"joe",last:"jamea"}})
错误写法:db.user.find({name:{last:"jamea",first:"joe"}})
注意顺序不能错 元素也不能少
加入加个middle-name 那么第一种写法也是错误的
db.user.find({name:{first:"joe",middle:"XXXX",last:"jamea"}})
保险写法:
db.user.find({"name.first":"joe","name.last":"jamea"})
比较复杂的一种内嵌文档处理
{
content:"......",
"comments":[
{
"author":"joe",
"score":3,
"comment":"nice posts"
},
{
"author":"marry",
"score":6,
"comment":"terriable posts"
}
]
}
查询joe 5分以上的评论
2种错误写法:
db.blog.find({comments:{author:"joe",score:{$gte:5}}})
错误原因:文档不匹配
db.blog.find({"comments.author":"joe","comments.score":{$gte:5}})
错误原因:"comments.author":"joe" 数组第一项匹配
"comments.score":{$gte:5} 数组第二项匹配
总的匹配上了 其实它并没有匹配上
正确写法
db.blog.find({"comments":{$elemMatch:{author:"joe",score:{$gte:5}}}})
$elemMatch:将限定条件进行分组
5).$where 查询
查询文档中有两个键的值是否相等 相等返回文档
db.foo.insert({banana:1,apple:2,peach:2})
db.foo.insert({banana:1,peach:3,apple:2})
db.foo.find({$where:function(){
for(var current in this){
for(var other in this){
if(current!=other && this[current]==this[other])
return true;
}
}
return false;
}})
$where 不仅可以用函数 也能用表达式
db.foo.find({"$where":"this.x+this.y==10"})
db.foo.find({"$where":"function(){return this.x+this.y==10}}")
不是必要要避免使用$where
10.游标
for(i =0 ;i<100;i++){
db.c.insert({x:1});
}
var cursor = db.c.find();
while(cursor.hasNext()){
obj = cursor.next();
//do something
}
游标还实现了 迭代器借口 所以可以用 forEach(fn)
cursor.forEach(function(x){println(x.name)})
调用find的时候 shell并不立即查询数据库
var cursor = db.foo.find().sort({"x":1}).limut(1).skip(10);
var cursor = db.foo.find().limut(1).sort({"x":1}).skip(10);
var cursor = db.foo.find().skip(10).sort({"x":1}).limut(1);
当执行cursor.hasNext()获取前100个结果 或者前4MB数据
limit:限制返回结果
db.c.find().limit(3)
最多只返回3个结果
skip:忽略前面几个匹配的文档
db.c.find().skip(3)
略过前面3个匹配文档,然后返回余下的文档,如果匹配的
文档少于3个 则不会返回任何文档
sort:排序
db.c.find().sort({username:1,age:-1})
按username那么升序 age降序排序
这3个一起使用可以弄分页
业务需求:搜索MP3 每页50个结果 按价格降序
第一页: db.stock.find({desc:"Mp3"}).limit(50).sort({"price":-1})
点击下一页
db.stock.find({desc:"Mp3"}).skip(50).limit(50).sort({"price":-1})
略过前几条 对性能要求比较高 少用...
11.不用skip进行分页
用skip
var page1 = db.foo.find(query).limit(100)
var page2 = db.foo.find(query).skip(100).limit(100)
var page3 = db.foo.find(query).skip(200).limit(100)
...
不用skip
var page1 = db.foo.find().sort({"date",-1}).limit(100)
var latest = null
while(page1.hasNext()){
latest = page1.next();
display(latest);
}
var page2 = db.foo.find({date:{$gt:latest.date}}).sort({"date",-1}).limit(100)
12.随机选取文档
方法一:
var total = db.foo.count()
var random =Math.floor(Math.random()*total)
db.foo.find().skip(random).limit(1)
方法二:
db.people.insert({"name":"joe","random":Math.random()})
db.people.insert({"name":"zhangsan","random":Math.random()})
db.people.insert({"name":"wangjie","random":Math.random()})
var random = Math.random();
var res = db.people.find({"random":{"$gt":random}})
if(res == null)
res = db.people.find({"random":{"$lte":random}})
13 高级查询
14 获得一致结果
需要使用:$snapshot
15:游标内幕
数据库10分钟后自动消失 需要程序手动的去提醒数据库别让游标过期