学习一个新的数据库,一般怎么下手呢?基本的CURD没跑了,当可以熟练的增、删、改、查一个数据库时,可以说对这个数据库算是入门了,如果需要更进一步的话,就需要了解下数据库的特性,比如索引、事物、锁、分布式支持等
本篇博文为mongodb的入门篇,将介绍一下基本的查询操作,在Spring中可以怎么玩
原文可参看:190113-SpringBoot高级篇MongoDB之查询基本使用姿势
在正式开始之前,先准备好环境,搭建好工程,对于这一步的详细信息,可以参考博文:181213-SpringBoot高级篇MongoDB之基本环境搭建与使用
接下来,在一个集合中,准备一下数据如下,我们的基本查询范围就是这些数据
最常见的查询场景,比如我们根据查询user=一灰灰blog的数据,这里主要会使用Query+Criteria来完成
@Component publicclassMongoReadWrapper{ privatestaticfinalStringCOLLECTION_NAME="demo"; @Autowired privateMongoTemplatemongoTemplate; /** *指定field查询 */ publicvoidspecialFieldQuery(){ Queryquery=newQuery(Criteria.where("user").is("一灰灰blog")); //查询一条满足条件的数据 Mapresult=mongoTemplate.findOne(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|specialFieldQueryOne:"+result); //满足所有条件的数据 List<Map>ans=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|specialFieldQueryAll:"+ans); } }上面是一个实际的case,从中可以知道一般的查询方式为:
Criteria.where(xxx).is(xxx)来指定具体的查询条件 封装Query对象newQuery(criteria) 借助mongoTemplate执行查询mongoTemplate.findOne(query,resultType,collectionName)其中findOne表示只获取一条满足条件的数据;find则会将所有满足条件的返回;上面执行之后,删除结果如
query:Query:{"user":"一灰灰blog"},Fields:{},Sort:{}|specialFieldQueryOne:{_id=5c2368b258f984a4fda63cee,user=一灰灰blog,desc=帅气逼人的码农界老秀} query:Query:{"user":"一灰灰blog"},Fields:{},Sort:{}|specialFieldQueryAll:[{_id=5c2368b258f984a4fda63cee,user=一灰灰blog,desc=帅气逼人的码农界老秀},{_id=5c3afaf4e3ac8e8d2d39238a,user=一灰灰blog,desc=帅气逼人的码农界老秀3},{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0},{_id=5c3b003ee3ac8e8d2d39238f,user=一灰灰blog,desc=帅气逼人的码农界老秀6,sign=helloworld}]前面是只有一个条件满足,现在如果是要求同时满足多个条件,则利用org.springframework.data.mongodb.core.query.Criteria#and来斜街多个查询条件
/** *多个查询条件同时满足 */ publicvoidandQuery(){ Queryquery=newQuery(Criteria.where("user").is("一灰灰blog").and("age").is(18)); Mapresult=mongoTemplate.findOne(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|andQuery:"+result); }删除结果如下
query:Query:{"user":"一灰灰blog","age":18},Fields:{},Sort:{}|andQuery:{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0}and对应的就是or,多个条件中只要一个满足即可,这个与and的使用有些区别,借助org.springframework.data.mongodb.core.query.Criteria#orOperator来实现,传参为多个Criteria对象,其中每一个表示一种查询条件
/** *或查询 */ publicvoidorQuery(){ //等同于db.getCollection(demo).find({"user":"一灰灰blog",$or:[{"age":18},{"sign":{$exists:true}}]}) Queryquery=newQuery(Criteria.where("user").is("一灰灰blog") .orOperator(Criteria.where("age").is(18),Criteria.where("sign").exists(true))); List<Map>result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|orQuery:"+result); //单独的or查询 //等同于Query:{"$or":[{"age":18},{"sign":{"$exists":true}}]},Fields:{},Sort:{} query=newQuery(newCriteria().orOperator(Criteria.where("age").is(18),Criteria.where("sign").exists(true))); result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|orQuery:"+result); }执行后输出结果为
query:Query:{"user":"一灰灰blog","$or":[{"age":18},{"sign":{"$exists":true}}]},Fields:{},Sort:{}|orQuery:[{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b003ee3ac8e8d2d39238f,user=一灰灰blog,desc=帅气逼人的码农界老秀6,sign=helloworld}] query:Query:{"$or":[{"age":18},{"sign":{"$exists":true}}]},Fields:{},Sort:{}|orQuery:[{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b003ee3ac8e8d2d39238f,user=一灰灰blog,desc=帅气逼人的码农界老秀6,sign=helloworld},{_id=5c3b0538e3ac8e8d2d392390,user=二灰灰blog,desc=帅气逼人的码农界老秀6,sign=helloworld}]标准的in查询case
/** *in查询 */ publicvoidinQuery(){ //相当于: Queryquery=newQuery(Criteria.where("age").in(Arrays.asList(18,20,30))); List<Map>result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|inQuery:"+result); }输出
query:Query:{"age":{"$in":[18,20,30]}},Fields:{},Sort:{}|inQuery:[{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0}]数值的比较大小,主要使用的是get,gt,lt,let
/** *数字类型,比较查询> */ publicvoidcompareBigQuery(){ //age>18 Queryquery=newQuery(Criteria.where("age").gt(18)); List<Map>result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|compareBigQuery:"+result); //age>=18 query=newQuery(Criteria.where("age").gte(18)); result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|compareBigQuery:"+result); } /** *数字类型,比较查询< */ publicvoidcompareSmallQuery(){ //age<20 Queryquery=newQuery(Criteria.where("age").lt(20)); List<Map>result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|compareSmallQuery:"+result); //age<=20 query=newQuery(Criteria.where("age").lte(20)); result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|compareSmallQuery:"+result); }输出
query:Query:{"age":{"$gt":18}},Fields:{},Sort:{}|compareBigQuery:[{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0}] query:Query:{"age":{"$gte":18}},Fields:{},Sort:{}|compareBigQuery:[{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0}] query:Query:{"age":{"$lt":20}},Fields:{},Sort:{}|compareSmallQuery:[{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0}] query:Query:{"age":{"$lte":20}},Fields:{},Sort:{}|compareSmallQuery:[{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0}]牛逼高大上的功能
/** *正则查询 */ publicvoidregexQuery(){ Queryquery=newQuery(Criteria.where("user").regex("^一灰灰blog")); List<Map>result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|regexQuery:"+result); }输出
query:Query:{"user":{"$regex":"^一灰灰blog","$options":""}},Fields:{},Sort:{}|regexQuery:[{_id=5c2368b258f984a4fda63cee,user=一灰灰blog,desc=帅气逼人的码农界老秀},{_id=5c3afacde3ac8e8d2d392389,user=一灰灰blog2,desc=帅气逼人的码农界老秀2},{_id=5c3afaf4e3ac8e8d2d39238a,user=一灰灰blog,desc=帅气逼人的码农界老秀3},{_id=5c3afafbe3ac8e8d2d39238b,user=一灰灰blog4,desc=帅气逼人的码农界老秀4},{_id=5c3afb0ae3ac8e8d2d39238c,user=一灰灰blog5,desc=帅气逼人的码农界老秀5},{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0},{_id=5c3b003ee3ac8e8d2d39238f,user=一灰灰blog,desc=帅气逼人的码农界老秀6,sign=helloworld}]统计常用,这个主要利用的是mongoTemplate.count方法
/** *查询总数 */ publicvoidcountQuery(){ Queryquery=newQuery(Criteria.where("user").is("一灰灰blog")); longcnt=mongoTemplate.count(query,COLLECTION_NAME); System.out.println("query:"+query+"|cnt"+cnt); }输出
query:Query:{"user":"一灰灰blog"},Fields:{},Sort:{}|cnt5这个对应的是mysql中的group查询,但是在mongodb中,更多的是通过聚合查询,可以完成很多类似的操作,下面借助聚合,来看一下分组计算总数怎么玩
/* *分组查询 */ publicvoidgroupQuery(){ //根据用户名进行分组统计,每个用户名对应的数量 //aggregate([{"$group":{"_id":"user","userCount":{"$sum":1}}}]) Aggregationaggregation=Aggregation.newAggregation(Aggregation.group("user").count().as("userCount")); AggregationResults<Map>ans=mongoTemplate.aggregate(aggregation,COLLECTION_NAME,Map.class); System.out.println("query:"+aggregation+"|groupQuery"+ans.getMappedResults()); }注意下,这里用Aggregation而不是前面的Query和Criteria,输出如下
query:{"aggregate":"__collection__","pipeline":[{"$group":{"_id":"$user","userCount":{"$sum":1}}}]}|groupQuery[{_id=一灰灰blog,userCount=5},{_id=一灰灰blog2,userCount=1},{_id=一灰灰blog4,userCount=1},{_id=二灰灰blog,userCount=1},{_id=一灰灰blog5,userCount=1}]sort,比较常见的了,在mongodb中有个有意思的地方在于某个字段,document中并不一定存在,这是会怎样呢?
/** *排序查询 */ publicvoidsortQuery(){ //sort查询条件,需要用with来衔接 Queryquery=Query.query(Criteria.where("user").is("一灰灰blog")).with(Sort.by("age")); List<Map>result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|sortQuery"+result); }输出结果如下,对于没有这个字段的document也被查出来了
query:Query:{"user":"一灰灰blog"},Fields:{},Sort:{"age":1}|sortQuery[{_id=5c2368b258f984a4fda63cee,user=一灰灰blog,desc=帅气逼人的码农界老秀},{_id=5c3afaf4e3ac8e8d2d39238a,user=一灰灰blog,desc=帅气逼人的码农界老秀3},{_id=5c3b003ee3ac8e8d2d39238f,user=一灰灰blog,desc=帅气逼人的码农界老秀6,sign=helloworld},{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0}]数据量多的时候,分页查询比较常见,用得多就是limit和skip了
/** *分页查询 */ publicvoidpageQuery(){ //limit限定查询2条 Queryquery=Query.query(Criteria.where("user").is("一灰灰blog")).with(Sort.by("age")).limit(2); List<Map>result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|limitPageQuery"+result); //skip()方法来跳过指定数量的数据 query=Query.query(Criteria.where("user").is("一灰灰blog")).with(Sort.by("age")).skip(2); result=mongoTemplate.find(query,Map.class,COLLECTION_NAME); System.out.println("query:"+query+"|skipPageQuery"+result); }输出结果表明,limit用来限制查询多少条数据,skip则表示跳过前面多少条数据
query:Query:{"user":"一灰灰blog"},Fields:{},Sort:{"age":1}|limitPageQuery[{_id=5c2368b258f984a4fda63cee,user=一灰灰blog,desc=帅气逼人的码农界老秀},{_id=5c3afaf4e3ac8e8d2d39238a,user=一灰灰blog,desc=帅气逼人的码农界老秀3}] query:Query:{"user":"一灰灰blog"},Fields:{},Sort:{"age":1}|skipPageQuery[{_id=5c3b003ee3ac8e8d2d39238f,user=一灰灰blog,desc=帅气逼人的码农界老秀6,sign=helloworld},{_id=5c3afb1ce3ac8e8d2d39238d,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=18.0},{_id=5c3b0031e3ac8e8d2d39238e,user=一灰灰blog,desc=帅气逼人的码农界老秀6,age=20.0}]上面给出的一些常见的查询姿势,当然并不全面,比如我们如果需要查询document中的部分字段怎么办?比如document内部结果比较复杂,有内嵌的对象或者数组时,嵌套查询可以怎么玩?索引什么的又可以怎么利用起来,从而优化查询效率?如何通过传说中自动生成的_id来获取文档创建的时间戳?
先留着这些疑问,后面再补上
一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
微博地址:小灰灰Blog QQ:一灰灰/3302797840一灰灰blog
知识星球
本文内容总结:I.基本使用,0.环境准备,1.根据字段进行查询,2.and多条件查询,3.or或查询,4.in查询,5.数值比较,6.正则查询,7.查询总数,8.分组查询,9.排序,10.分页,11.小结,II.其他,0.项目,1.一灰灰Blog,2.声明,3.扫描关注,
原文链接:https://www.cnblogs.com/yihuihui/p/10264113.html