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

[经验分享] MongoDB高级查询用法大全

[复制链接]

尚未签到

发表于 2015-7-8 06:36:32 | 显示全部楼层 |阅读模式
  转载 http://blog.163.com/lgh_2002/blog/static/440175262012052116455/
  详见官方的手册:
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ConditionalOperators%3A%3C%2C%3C%3D%2C%3E%2C%3E%3D
版本一:
1 ) . 大于,小于,大于或等于,小于或等于
$gt:大于
$lt:小于
$gte:大于或等于
$lte:小于或等于
例子:





db.collection.find({ "field" : { $gt: value } } );   // greater than  : field > value
db.collection.find({ "field" : { $lt: value } } );   // less than  :  field < value
db.collection.find({ "field" : { $gte: value } } );  // greater than or equal to : field >= value
db.collection.find({ "field" : { $lte: value } } );  // less than or equal to : field  t.find( { "x.a" : 1, "x.b" : { $gt : 1 } } )
  $elemMatch是匹配{ "a" : 1, "b" : 3 },而后面一句是匹配{ "b" : 99 }, { "a" : 11 }
12)  查询嵌入对象的值





db.postings.find( { "author.name" : "joe" } );
  注意用法是author.name,用一个点就行了。更详细的可以看这个链接: dot notation
  举个例子:





> db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})
  如果我们要查询 authors name 是Jane的, 我们可以这样:





> db.blog.findOne({"author.name" : "Jane"})
  如果不用点,那就需要用下面这句才能匹配:





db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})
  下面这句:





db.blog.findOne({"author" : {"name" : "Jane"}})
  是不能匹配的,因为mongodb对于子对象,他是精确匹配。
  
  13) 元操作符 $not 取反
  如:





db.customers.find( { name : { $not : /acme.*corp/i } } );




db.things.find( { a : { $not : { $mod : [ 10 , 1 ] } } } );

  mongodb还有很多函数可以用,如排序,统计等,请参考原文。
mongodb目前没有或(or)操作符,只能用变通的办法代替,可以参考下面的链接:
http://www.mongodb.org/display/DOCS/OR+operations+in+query+expressions
版本二:



  shell 环境下的操作:
      1.   超级用户相关:
            1. #进入数据库admin
               use admin
           2. #增加或修改用户密码
            db.addUser('name','pwd')
           3. #查看用户列表
             db.system.users.find()
           4. #用户认证
            db.auth('name','pwd')
           5. #删除用户
             db.removeUser('name')
           6.  #查看所有用户
             show users
            7. #查看所有数据库
             show dbs
            8. #查看所有的collection
             show collections
            9. #查看各collection的状态
             db.printCollectionStats()
           10. #查看主从复制状态
             db.printReplicationInfo()
           11. #修复数据库
             db.repairDatabase()
           12. #设置记录profiling,0=off 1=slow 2=all
             db.setProfilingLevel(1)
           13. #查看profiling
             show profile
           14. #拷贝数据库
             db.copyDatabase('mail_addr','mail_addr_tmp')
           15. #删除collection
             db.mail_addr.drop()
           16. #删除当前的数据库
             db.dropDatabase()
      2. 增删改
           1.  #存储嵌套的对象
               db.foo.save({'name':'ysz','address':{'city':'beijing','post':100096},'phone':[138,139]})
           2. #存储数组对象
               db.user_addr.save({'Uid':'yushunzhi@sohu.com','Al':['test-1@sohu.com','test-2@sohu.com']})
           3. #根据query条件修改,如果不存在则插入,允许修改多条记录
               db.foo.update({'yy':5},{'$set':{'xx':2}},upsert=true,multi=true)
           4. #删除yy=5的记录
               db.foo.remove({'yy':5})
           5. #删除所有的记录
               db.foo.remove()
      3. 索引
            1. #增加索引:1(ascending),-1(descending)
           2. db.foo.ensureIndex({firstname: 1, lastname:  1}, {unique: true});
           3. #索引子对象
           4. db.user_addr.ensureIndex({'Al.Em':  1})
           5. #查看索引信息
           6. db.foo.getIndexes()
           7. db.foo.getIndexKeys()
           8. #根据索引名删除索引
           9. db.user_addr.dropIndex('Al.Em_1')
      4. 查询
            1. #查找所有
           2. db.foo.find()
           3. #查找一条记录
           4. db.foo.findOne()
           5. #根据条件检索10条记录
           6. db.foo.find({'msg':'Hello 1'}).limit(10)
           7. #sort排序
          8.  db.deliver_status.find({'From':'ixigua@sina.com'}).sort({'Dt',-1})
           9.  db.deliver_status.find().sort({'Ct':-1}).limit(1)
           10. #count操作
           11. db.user_addr.count()
           12. #distinct操作,查询指定列,去重复
           13. db.foo.distinct('msg')
           14. #”>=”操作
           15. db.foo.find({"timestamp": {"$gte" : 2}})
           16. #子对象的查找
           17. db.foo.find({'address.city':'beijing'})
      5. 管理
            1. #查看collection数据的大小
           2. db.deliver_status.dataSize()
           3. #查看colleciont状态
           4. db.deliver_status.stats()
           5. #查询所有索引的大小
           6.  db.deliver_status.totalIndexSize()
  
  6.  高级查询

条件操作符
$gt  : >
$lt : <
$gte: >=
$lte: = 18 的数据
db.users.find({name:  {$ne: "bruce"}, age: {$gte: 18}});
查询  creation_date > '2010-01-01' and creation_date  18 的记录,以下查询都一样
db.users.find({age:  {$gt: 18}});
db.users.find({$where: "this.age >  18"});
db.users.find("this.age > 18");
f = function() {return  this.age > 18} db.users.find(f);
排序sort()
以年龄升序asc
db.users.find().sort({age:  1});
以年龄降序desc
db.users.find().sort({age:  -1});
限制返回记录数量limit()
返回5条记录
db.users.find().limit(5);
返回3条记录并打印信息
db.users.find().limit(3).forEach(function(user)  {print('my age is ' + user.age)});
结果
my  age is 18
my age is 19
my age is  20
限制返回记录的开始点skip()
从第3条记录开始,返回5条记录(limit  3,  5)
db.users.find().skip(3).limit(5);
查询记录条数count()
db.users.find().count();
db.users.find({age:18}).count();
以下返回的不是5,而是user表中所有的记录数量
db.users.find().skip(10).limit(5).count();
如果要返回限制之后的记录数量,要使用count(true)或者count(非0)
db.users.find().skip(10).limit(5).count(true);
分组group()
假设test表只有以下一条数据
{  domain: "www.mongodb.org"
, invoked_at: {d:"2009-11-03", t:"17:14:05"}
,  response_time: 0.05
, http_action: "GET  /display/DOCS/Aggregation"
}
使用group统计test表11月份的数据count:count(*)、total_time:sum(response_time)、avg_time:total_time/count;
db.test.group(
{  cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}
, key:  {http_action: true}
, initial: {count: 0, total_time:0}
, reduce:  function(doc, out){ out.count++; out.total_time+=doc.response_time }
,  finalize: function(out){ out.avg_time = out.total_time / out.count }
}  );
[
{
"http_action" : "GET  /display/DOCS/Aggregation",
"count" : 1,
"total_time" :  0.05,
"avg_time" : 0.05
}
]






MongoDB 高级聚合查询
  MongoDB版本为:2.0.8  
  系统为:64位Ubuntu 12.04
  先给他家看一下我的表结构[Oh sorry, Mongo叫集合]
DSC0000.png
  如你所见,我尽量的模拟现实生活中的场景。这是一个人的实体,他有基本的manId, manName, 有朋友[myFriends],有喜欢的水果[fruits],而且每种水果都有喜欢的权重。
  很不好的是你还看见了有个“_class”字段? 因为我是Java开发者, 我还喜欢用Spring,因此我选用了Spring Data Mongo的类库[也算是框架吧,但是我不这么觉得]。
  现在有很多人Spring见的腻了也开始烦了。是的,Spring野心很大,他几乎想要垄断Java方面的任何事情。没办法我从使用Spring后就离不开他,以至于其他框架基本上都不用学。我学了Spring的很多,诸如:Spring Security/Spring Integration/Spring Batch等。。。不发明轮子的他已经提供了编程里的很多场景,我利用那些场景解决了工作中的很多问题,也使我的工作变得很高效。从而我又时间学到它更多。Spring Data Mongo封装了mongodb java driver,提供了和SpringJDBC/Template一致编程风格的MongoTemplate。
  见:http://static.springsource.org/spring-data/data-mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoTemplate.html
  不说废话了,我们直接来MongoDB吧。


  • Max 和Min
  我和同事在测试Mongo时,索引还写了不到一半,他想查询某个字段的最大值,结果找了半天文档也没找到关于max的函数。我也很纳闷这是常规函数啊怎么不提供? 后来经过翻阅资料确定Mongo确实不提供直接的max和min函数。但是可以通过间接的方式[sort 和 limit]实现这个。
  要查询最大值我们只需要把结果集按照降序排列,取第一个值就是了。
  如我的例子,我想取得集合中年龄最大的人。







1db.person.find({}).sort({"age" : -1}).limit(1)
  相反如果想要年龄最小的人,只需要把sort中改为{“age”:1}就可以了。
  当然我们使用了sort,对于小数量的文档是没问题的。当对于大量数据需要给age建立索引,否则这个操作很耗时。


  • distinct
  MongoDB的destinct命令是获取特定字段中不同值列表的最简单工具。该命令适用于普通字段,数组字段[myFriends]和数组内嵌文档[fruits].
  如上面的图片,我认为fruits和myFriends字段是不同的。网上很多资料和例子都没说到这个情景,因为我们也业务是fruits这样的模型,我测试了。对于fruits.fruitId他也是可行的。
  如上面的表结构,我想统计所有的喜欢的水果。



db.person.distinct("fruits.fruitId") // 查找对象里引入对象的值,直接加.

  他成功执行了。输出如:



[ "aaa", "bbb", "ccc", "www", "xxx", "yyy", "zzz", "rrr" ]

  我想统计集合中共有多少个人[按名字吧]



db.person.distinct("manName")

  我想统计指定个数的人的共同关注的朋友。



db.person.distinct("myFriends", {"manName" : {"$in" : ["ZhenQin", "YangYan"]}})

  输出如:



[ "234567", "345678", "456789", "987654", "ni", "wo" ]

  
  那么我使用Java呢? 我只是在演示Mongo的命令,用Spring Data Mongo是怎么操作的?
  Spring Schema:













  maxmin的测试



@Test
public void testMaxAndMinAge() throws Exception {
Query q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.ASC, "age"))).limit(1);
Person result = mongoTemplate.findOne(q, Person.class);
log.info(result);
q = new BasicQuery("{}").with(new Sort(new Sort.Order(Sort.Direction.DESC, "age"))).limit(1);
result = mongoTemplate.findOne(q, Person.class);
log.info(result);
}

  distinct的测试:



@Test
public void testDistinct() throws Exception {
List result = mongoTemplate.getCollection("person").distinct("myFriends");
for (Object o : result) {
log.info(o);
}
log.info("==================================================================");
Query query = Query.query(Criteria.where("manId").is("123456"));
result = mongoTemplate.getCollection("person").distinct("myFriends", query.getQueryObject());
for (Object o : result) {
log.info(o);
}
log.info("==================================================================");
result = mongoTemplate.getCollection("person").distinct("fruits.fruitId");
for (Object o : result) {
log.info(o);
}
}

  输出的结果为:



12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 234567
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 345678
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 456789
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 987654
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] ni
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] wo
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(72)] 123456
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(75)] ==================================================================
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 234567
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 345678
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 456789
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(79)] 987654
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(82)] ==================================================================
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] aaa
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] bbb
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] ccc
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] www
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] xxx
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] yyy
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] zzz
12-22 14:13:45 [INFO] [t.MongoAdvaceQueryTest(85)] rrr
12-22 14:13:45 [INFO] [support.GenericApplicationContext(1020)] Closing org.springframework.context.support.GenericApplicationContext@1e0a91ff: startup date [Sat Dec 22 14:13:44 CST 2012]; root of context hierarchy

  这里我要特别说明一下, 当使用了Spring Data Mongo,如上面的findOne(query, Person.class)它就会把查询的结果集转换成Person类的对象。Spring Data Mongo的很多API中都这样,让传入了一个Bean的class对象。因为distinct的测试是输出list的,我 使用的mongo-java-driver的api。他们都很简单,唯一的是Query这个Spring提供的对象,希望读者注意,他几乎封装了所有条件 查询,sort,limit等信息。

运维网声明 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-84202-1-1.html 上篇帖子: MongoDB学习笔记(一)MongoDB概述和安装 下篇帖子: MongoDB 3.0 配置文件
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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