spring-data-mongo 实现aggregation

摘要

mongo aggregation是mongo 的一个轻量级的map-reduce框架,可以实现一些count,sum,groupby的聚合。本身的意义就在于减少查询次数,将原本需要客户端的多次查询能够整合到db端的基于pipeline的查询。这样带来的好处就是减少请求数据库次数,坏处就是这个查询占用的数据库内存大,时间查,有可能拖垮其他查询。这个在本篇文章不讨论。

概述

常用的阶段函数

  • $match: 就是where查询

  • $group : 就是group by

  • $project:添加新字段/重置已有字段,比如group阶段的key值会变成_id就需要

  • $unwind :将数组拆分为几个字段

  • $sort 排序

  • $limit 限制条数

  • $skip 跳过条数

例子

  1. java 配置 mongo 连接

    @Configuration
    @EnableMongoRepositories(basePackages = "com.fs.mongo.dao")
    public class MongoConfig extends AbstractMongoConfiguration {
    
        @Bean
        public MongoDbFactory mongoDbFactory() throws UnknownHostException {
            MongoClientOptions options = new MongoClientOptions.Builder().connectionsPerHost(8).build();
            return new SimpleMongoDbFactory(new MongoClient("localhost",options ),"test");
        }
        // 默认数据库会生成_class字段,需要更改mappingMongoConverter的typeMappper属性值
        @Bean
        public MongoTemplate mongoTemplate() throws Exception {
            return new MongoTemplate(mongoDbFactory(),mappingMongoConverter());
        }
    
        protected String getDatabaseName() {
            return "test";
        }
    
        @Bean
        public Mongo mongo() throws Exception {
            return new MongoClient();
        }
    
        @Bean
        @Override
        public MappingMongoConverter mappingMongoConverter() throws Exception {
            MappingMongoConverter converter = new         MappingMongoConverter(mongoDbFactory(),this.mongoMappingContext());
            converter.setTypeMapper(new DefaultMongoTypeMapper(null));
            return converter;
        }
    }
  2. 基于mongoTemplate 发送aggregate请求

    @Component
    public class PostDb {
        @Autowired
        private MongoTemplate mongoTemplate;
    
        public PostDb(MongoTemplate mongoTemplate) {
            this.mongoTemplate = mongoTemplate;
        }
        public List<Post> getPeopleAggregationByCategory(long userId) {
            MatchOperation match = Aggregation.match(new Criteria("userId").is(userId));
            GroupOperation group  = Aggregation.group("category").count().as("total");
            // 注group key category会映射成_id,所以要利用project阶段映射回category
            ProjectionOperation project =  Aggregation.project("total").and("_id").as("category");
            Aggregation aggregation = Aggregation.newAggregation(match,group,project);
            AggregationResults<Post> results = mongoTemplate.aggregate(aggregation,"post",Post.class);
            return results.getMappedResults();
        }
    }

完整代码:
https://github.com/FS1360472174/nosql-mongo/tree/master/project/sample/sample-mongo-aggregation

扫码关注NoSQL开发公众号,第一时间接收文章推送
这里写图片描述

MongoTemplate().aggregate()做聚合查询返回结果不对

02-19
上代码: Criteria c = Criteria.where("storeId") .is(hotelId) .and("bussDate") .gte(startDate) .lt(endDate); if(t == 1){ c.and("dishAttr").nin(372); }else{ c.and("dishAttr").nin(373); } //Query q = new Query(c); if(pageNum == 1){ pageNum -= 1; }else{ pageSize = pageSize * pageNum; pageNum = (pageNum - 1) * 20; } //q.skip(pageNum).limit(pageSize); Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(c), Aggregation.group("dishName").sum("makeNum").as("makeNum").sum("makeAmount").as("makeAmount"), Aggregation.skip(pageNum), Aggregation.limit(pageSize) ); System.out.println("--mongoDBSQL--"+aggregation.toString()); AggregationResults<RptDailyDishSale> aggRes = this.getMongoTemplate().aggregate(aggregation, "rptDailyDishSale", RptDailyDishSale.class); List<RptDailyDishSale> listRes = aggRes.getMappedResults(); for (RptDailyDishSale rptDailyDishSale : listRes) { System.out.println("--菜类名称:--"+rptDailyDishSale.getSortName()+"--菜品名称:--"+rptDailyDishSale.getDishNam()); //**问题来了!!!!!** 打印的rptDailyDishSale.getDishNam() 名称是 null debug的时候 截图如下 ![图片说明](https://img-ask.csdn.net/upload/201602/19/1455863480_211441.jpg) } return listRes; 打印出来的sql语句 ---------------------------------- --mongoDBSQL--{ "aggregate" : "__collection__" , "pipeline" : [ { "$match" : { "storeId" : "14e714b8-8c68-445c-a74a-3cc5a13afef2" , "bussDate" : { "$gte" : "2016-02-18" , "$lt" : "2016-02-19"} , "dishAttr" : { "$nin" : [ 373]}}} , { "$group" : { "_id" : "$dishName" , "makeNum" : { "$sum" : "$makeNum"} , "makeAmount" : { "$sum" : "$makeAmount"}}} , { "$skip" : 0} , { "$limit" : 20}]}
©️2020 CSDN 皮肤主题: Age of Ai 设计师: meimeiellie 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值