设为首页 收藏本站
查看: 3067|回复: 0

[经验分享] MongoDB笔记-查询

[复制链接]

尚未签到

发表于 2015-7-8 12:06:28 | 显示全部楼层 |阅读模式
  find()
  查询结合的所有内容,如db.users.find({"age":27,"username":"joe"})
  第二个参数控制返回指定的键
  返回指定的键“age”:db.users.find({},{"age":1})
  剔除指定的键“age”:db.users.find({},{"age":0})
  限制:文档的值必须是常量,如果需要查询变量则需要修改文档,以转化为常量查询方式。
  查询条件
  条件:"$lt","$lte","$gt","$gte","$ne"(适应于所有数据类型) 分别对应=,!=
  db.users.find({"age":{"$gte":10,"$lte":30}})  10-30(含)岁之间的用户
  OR
  "$in","$nin"单一键与多个值匹配不匹配,可以与不同类型数据比较 db.raffle.find({"ticket_no":{"$in":[123,456,"789"]}})
  "$or"多个条件 db.raffle.find({"$or":[{"tick_no":{"$in":[123,456,"789"]}},{"winner":true}]})
  Not
  "$not"是元语句,可以作用在任何条件上,特别是与正则连用时
  如db.user.find({"id_num":{"$not":{"$mod":[5,1]}}}) 返回所有id除5不余1的用户
  查询针对外层文档,修改针对外层文档,修改器无法使用多次,如{"$inc":{"age":1},"set":{age:40}}是错误的,但是查询是可以的
  特定类型查询
  null
  匹配自身为null或“不存在” 键的文档
  db.c.find({"y":null})  会返回所有y=null或者不含y键的文档
  如果仅仅返回自身为null的,需要配合"$exits"
  db.c.find({"y":{"$in":[null],"$exits":true}})  注意,因为没有用"$eq"的操作符,只能采用单元素的"$in"操作符替代
  正则表达式
  采用Perl兼容的正则表达式PCRE库来匹配正则,可用Javascript Shell检查语法,另外,可用前缀型正则表达式(如/^joey/)创建索引,所以这种类型的查询很高效
  db.users.find({"name":/joey?/i})
  也可匹配自身,即把正则表达式作为值存入文档也是可以匹配的(虽然几乎没人这么做)
  db.user.insert({"bar":/baz/})
  db.user.find({"bar":/baz/})
  查询数组
  数组的查询可以理解为每一个数组中的元素都是该键的值
  db.food.insert({"fruit":["apple","banana","peach"]})  查询db.food.find({"fruit":"apple"})会成功匹配该文档
  "$all"多个元素匹配数组  db.food.find({"fruit":{$all:["apple","banana"]}}) 顺序无关紧要
         数组的完整精确匹配  db.food.find({"fruit":["apple","banana","peach"]})是可以匹配刚插入的数据,但是db.food.find({"fruit":["apple","banana"]})却无法匹配
         组下标查询 db.food.find({"fruit.2":"peach"})  会找到数组中第三个元素与"peach"匹配的数组
  "$size"查询长度为指定值的数组,但是它不能与"$gt"等查询字句组合,因此范围查询需要增加一个size字段,并且在更新的时候"$inc":{"size":1},但是该技巧不能与"$addToSet"并用
  db.food.find({"fruit":{"$size":3}})
  "$slice"返回数组中的一个子集合
  db.blogs.findone({"criteria",{"comments":{"$slice":10}}})   返回前10条评论
  db.blogs.findone({"criteria",{"comments":{"$slice":-10}}})   返回后10条评论
  db.blogs.findone({"criteria",{"comments":{"$slice":[23,10]}}})   返回前24-33条评论,如果不足33,则返回24之后所有的
  注:除非特别声明,否则它将返回文档中所有的键,而其他键都是只返回查询的键。
  如有



{     
"title":"a blog list",
    "content":"...",
"comments":[ {"name":"joe","email":joe@163.com},
               {"name":"bob","email":bob@163.com}]
}
  
  db.blogs.findone({"criteria",{"comments":{"$slice":-1}}}) 返回的是":{"title":"a blog list","content":"...","comments":[{"name":"bob","email":bob@163.com}],把title,content键也都返回来了
   查询内嵌文档



{
"name":{
"first":"joe"
"last":"schmoe"
},
"age":45
}
  
  查询整个文档
  db.people.find({"name":{"first":"joe","last":"schmoe"}}) 是可以匹配的,但是这种查询是精确匹配,而且是顺序相关的,即:如果添加了一个"middle"将不会匹配,同理,如果{"last":"schmoe","first":"joe"}})同样不会匹配
  针对键值查询
  db.people.find({"name.first":"joe","name.last":"schmoe"}) 在name增加更多键后仍然匹配,"."表示法表示深入文档内部的含义,所以插入文档中不能包含"."关键字
  更为复杂的查询



{
"content":"...",
"comments":[
{
"author":"joe";
"score":3,
"comment":"nice post"
},
{
"author":"mary";
"score":6,
"comment":"terrible post"
}
]
}
  查找joe发表的5分以上的评论
  用db.blogs.find({"comments":{"author":"joe","score":{"$gt":5}}})  是无法匹配的,因为内嵌文档要求完全精确匹配
用db.blogs.find({"comments.author":"joe","comments.score":{"$gt":5}}) 也是无法匹配的,解释为:符合author和score的评论不一定是同一条评论,即author在第一条中匹配了,joe在第二条中匹配了。正确方法如下:
  "$elemMatch" db.blog.find({"comments":{"$elemMatch":{"author":"joe","score":{"$gt":5}}}})
   "$where"
  使用javascript作为查询的一部分,但是不推荐使用,因为其执行速度比常规查询缓慢,因为每个文档首先要从BSON转化为JS对象,还不能使用索引。
  如果必须使用,请先将常规查询作为条件进行过滤。或者用非"$where"进行过滤,用"$where"进行调优
  如一个文档:db.foo.insert({"apple":1,"spinach":4,"watermelon":4}) 我想找到spinach与watermelon值相同的文档,这种绝对不会有对应的"$"方法,只能自己依靠编程解决



db.foo.find("$where":function(){
for(var cur in this)
{
for(var other in this)
{
if(cur!=other&&this[cur]==this[other])
{
return true;
}
}
}
})
  返回true的这部分文档将会被返回
  游标
  控制返回结果的数量,忽略部分结果,根据任意方向任意键的组合对结果排序等
  var cursor=db.collection.find()
  迭代结果,可以用遍历方法



while(cursor.hasNext)
{
obj=cursor.next();
//do stuff
}
  游标类实现了迭代器接口



cursor.forEach(function(x)
{
print(x.name)
});
  调用find时,shell不去真正查库,而是在要求获得结果时才发送查询,很像c#中的延迟查询或延迟加载,因此可以加一系列的限定条件
  并且,因为游标对象的方法返回的是游标本身,因此可以按照任意顺序构成方法链。如下面三个完全等价。
  var cursor=db.foo.find().sort({"x":1}).limit(1).skip(10)  
var cursor=db.foo.find().skip(10) .sort({"x":1}).limit(1)
var cursor=db.foo.find().limit(1).sort({"x":1}).skip(10)
  但这时候查询并未执行,当发生cursor.hasNext()的时候,shell获取前100个或前4MB数据(较小者),这样next或者hasNext的时候都不用跑到服务器去请求,知道客户端用完第一组结果,shell才会再次联系数据库,请求更多结果,这个过程持续到游标耗尽或者结果全部返回。
  limit,skip,sort
  limit限制数量,skip略过数量,sort排序(1升序,-1降序,可以指定多个键)
  比较顺序:(由小到大),处理不同类型的数据是有顺序的,有时候一个键值有多个类型,其键排序是有序的
  最小值,null,数字,字符串,对象/文档,数组,二进制,对象id,布尔型,日期型,时间戳,正则表达式,最大值
  避免使用skip略过大量结果
  略过少量文档是不错的,但是略过大量文档就有性能问题(所有数据库都这样),所以推荐使用内置查询条件或者利用上次查询结果来进行下次查询
  不用skip分页(传统分页不说了,应该都知道)



//first page
var page1=db.foo.find().sort({"date":-1}).limit(100)
//display first page
while(page1.hasNext()){
latest=page1.next();
display(latest);
}
//next page
var page2=db.foo.find({"date":{"$gt":lastest.date}});
page2.sort({"date":-1}).limit(100);
  随机选取文档
  一般方法得到文档总数,然后随机,但是计算总数非常会很耗时,所以采用其他变通的方法,如向每个文档添加一个随机数,然后执行如下查询



var random=Math.random()
result=db.foo.findOne({"random":{"$gt":random}})
//if nothing in result, reverse the condition
if(result==null)
{
result=db.foo.findOne({"random":{"$lte":random}})
}
   高级查询选项
  架设执行如下查询:var cursor=db.foo.find({"foo":"bar"}).sort({"x":1}),执行机理为将查询包装到一个更大的文档中,{"$query":{"foo":"bar"},"$orderby":{"x":1}}
  大部分驱动有辅助措施添加各种选项,如
  $maxscan 最多扫描文档数量
  $min 开始的条件
  $max 结束的条件
  $hint 采用哪个索引
  $explain 获取查询细节(索引,数量,耗时),而不是真正执行
  $snapshot 确保查询的结果是在查询那一刻的一致快照
  获得一致结果
  数据处理的结果一般是从Mongodb中取出数据,处理然后在存回库中
  例如有把集合看做一大堆文档
  1、2、3、……、n
  把2提取出来进行了修改,变成了2',2'>2,并可能导致了文档体积增加而预留空间不足,于是吧2'放到了文档末尾,变成了
  1、3、……、n、2'
  游标继续向后获得文档,直到获取到2'!!
  处理方法为:对查询执行快照,使用了"$shapshot"的时候,查询是针对不变的集合视图进行的。
  游标内幕
  在服务器端的游标视角,游标会消耗内存和其他资源,因此要合理释放游标。释放游标的一些情况包括:完成匹配结果的迭代,客户端不在作用域内,超过10分钟未使用
  如果不想超时销毁游标,需要使用"immortal"函数

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-84477-1-1.html 上篇帖子: MongoDB 的 MapReduce 大数据统计统计挖掘 下篇帖子: mongodb的数据修改
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表