zoukankan      html  css  js  c++  java
  • Spring data mongodb 聚合,投射,内嵌数组文档分页.

    尽量别直接用 DBObject  ,Spring data mongodb 的api 本来就没什么多大用处,如果还直接用 DBObject 那么还需要自己去解析结果,说动做个对象映射,累不累

    Spring data mongodb 唯一好处就是,不需要自己decode encode,其他别的几乎也没了

    DBObject project = new BasicDBObject("$project", new BasicDBObject("_id", 1)
                   .append("..", "$..").append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1).append("..", 1)
                   .append("..", 1));
    
           query.add(project);
           query.add(new BasicDBObject("$unwind", "$..."));
           query.add(new BasicDBObject("$skip",...));
           query.add(new BasicDBObject("$limit",...));
     AggregationOutput aggregationOutput = mongoTemplate.getCollection("...").aggregate(query);

    以下使用Spring data mongodb 做聚合,内嵌文档分页,订单 - 明细 一对多的例子

    package com.example.mongo.entity;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    import org.bson.types.ObjectId;
    import org.springframework.data.annotation.Id;
    
    import java.io.Serializable;
    import java.util.List;
    
    /**
     * Created by laizhenwei on 2017/11/9
     */
    @Data
    @Accessors(chain = true)
    public class Order  implements Serializable {
    
    
        private static final long serialVersionUID = 4738576111790390042L;
    
        @Id
        private ObjectId objectId;
    
        private List<Detail> details;
    
        /**
         * 企业编号
         */
        private String compyCode;
    
        /**
         * 订单号
         */
        private String orderNo;
    
        /**
         * 用户名
         */
        private String userName;
    
    }

    明细实体

    package com.example.mongo.entity;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    import org.bson.types.ObjectId;
    
    import java.io.Serializable;
    import java.math.BigDecimal;
    
    /**
     * Created by laizhenwei on 2017/11/9
     */
    @Data
    @Accessors(chain = true)
    public class Detail  implements Serializable {
    
        private static final long serialVersionUID = 942116549431791887L;
    
        private ObjectId id;
    
        /**
         * 商品名称
         */
        private String productName;
    
        /**
         * 商品数量
         */
        private Long itemQty;
    
        /**
         * 单价
         */
        private BigDecimal price;
    
    }

    Junit

    package com.example.mongo.Repository;
    
    import com.example.mongo.entity.Detail;
    import com.example.mongo.entity.Order;
    import com.mongodb.BasicDBList;
    import com.mongodb.DBObject;
    import lombok.Data;
    import org.bson.types.ObjectId;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.aggregation.Aggregation;
    import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    
    import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
    import static org.springframework.data.mongodb.core.aggregation.Aggregation.limit;
    import static org.springframework.data.mongodb.core.query.Criteria.where;
    
    /**
     * Created by laizhenwei on 2017/11/9
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class OrderTests {
    
        @Autowired
        private OrderRepository orderRepository;
    
        @Autowired
        private MongoTemplate mongoTemplate;
    
        private String[] compyCode = {"123123", "456456", "789789"};
    
        private String[] userNames = {"Athos", "Peter", "Nero", "Gavin", "Carter"};
    
        /**
         * 造一点数据
         */
        @Test
        public void save() {
            List<Order> orders = new ArrayList<>(200);
            for (int i = 0; i < 200; i++) {
                List<Detail> details = new ArrayList<>(3);
                for (int j = 0; j < 3; j++) {
                    Detail detail = new Detail();
                    detail.setId(new ObjectId());
                    detail.setItemQty((long) (i + 1));
                    detail.setProductName("产品" + i + "_" + j);
                    detail.setPrice(new BigDecimal(10 + i));
                    details.add(detail);
                }
                Order order = new Order();
                order.setCompyCode(compyCode[i % 3]);
                order.setUserName(userNames[i % 5]);
                order.setOrderNo(String.valueOf(i));
                order.setDetails(details);
                orders.add(order);
            }
            orderRepository.insert(orders);
        }
    
    
        /**
         * 内嵌文档分页查询
         */
        @Test
        public void pageQuery() {
            Detail detailDto = new Detail();
    
            detailDto.setProductName("产品19_0");
    
            List<AggregationOperation> commonOperations = new ArrayList<>(9);
            commonOperations.add(project("objectId", "details", "compyCode", "orderNo", "userName").and("details").as("detail"));
            Optional.ofNullable(detailDto.getProductName()).ifPresent(s -> commonOperations.add(match(where("details.productName").is(detailDto.getProductName()))));
            commonOperations.add(unwind("detail"));
    
            List<AggregationOperation> pageOperations = new ArrayList<>(commonOperations);
            pageOperations.add(skip(1l));
            pageOperations.add(limit(10));
    
            List<AggregationOperation> totalAggOperation = new ArrayList<>(commonOperations);
            totalAggOperation.add(group().count().as("total"));
    
            List<DetailVo> results = mongoTemplate.aggregate(Aggregation.newAggregation(Order.class,pageOperations), Order.class, DetailVo.class).getMappedResults();
    
            System.out.println(results.size());
    
            DBObject rawResults = mongoTemplate.aggregate(Aggregation.newAggregation(Order.class,totalAggOperation), String.class).getRawResults();
            BasicDBList result = (BasicDBList)rawResults.get("result");
            long total = result.isEmpty() ? 0 : Long.parseLong(((DBObject)result.get(0)).get("total").toString());
    
            System.out.println("total:" + total);
        }
    
        /**
         *  结果实体
         */
        @Data
        private static class DetailVo{
            @Id
            private ObjectId orderId;
            private Detail detail;
            private String compyCode;
            private String orderNo;
            private String userName;
        }
    
    }

    logback 打开 方便观察

    <Logger name="org.mongodb.driver" level="debug" />
    <logger name="org.springframework.data.mongodb.core.MongoTemplate" level="debug" />

    控制台输出,只取重点,因为skip 了一个,所以结果只有2个,总数量是3个
    13:45:31.740 logback [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Executing aggregation: { "aggregate" : "order" , "pipeline" : [ { "$project" : { "objectId" : "$_id" , "details" : 1 , "compyCode" : 1 , "orderNo" : 1 , "userName" : 1 , "detail" : "$details"}} , { "$match" : { "details.productName" : "产品19_0"}} , { "$unwind" : "$detail"} , { "$skip" : 1} , { "$limit" : 10}]}
    13:45:31.743 logback [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[e9]
    13:45:31.752 logback [main] INFO  org.mongodb.driver.connection - Opened connection [connectionId{localValue:2}] to 192.168.1.9:27023
    13:45:31.756 logback [main] DEBUG org.mongodb.driver.protocol.command - Sending command {aggregate : BsonString{value='order'}} to database e9 on connection [connectionId{localValue:2}] to server 192.168.1.9:27023
    13:45:31.759 logback [main] DEBUG org.mongodb.driver.protocol.command - Command execution completed
    13:45:31.765 logback [main] DEBUG o.s.d.m.c.i.MongoPersistentEntityIndexCreator - Analyzing class class com.example.mongo.Repository.OrderTests$DetailVo for index information.
    2
    13:45:31.780 logback [main] DEBUG o.s.data.mongodb.core.MongoTemplate - Executing aggregation: { "aggregate" : "order" , "pipeline" : [ { "$project" : { "objectId" : "$_id" , "details" : 1 , "compyCode" : 1 , "orderNo" : 1 , "userName" : 1 , "detail" : "$details"}} , { "$match" : { "details.productName" : "产品19_0"}} , { "$unwind" : "$detail"} , { "$group" : { "_id" :  null  , "total" : { "$sum" : 1}}}]}
    13:45:31.780 logback [main] DEBUG o.s.data.mongodb.core.MongoDbUtils - Getting Mongo Database name=[e9]
    13:45:31.780 logback [main] DEBUG org.mongodb.driver.protocol.command - Sending command {aggregate : BsonString{value='order'}} to database e9 on connection [connectionId{localValue:2}] to server 192.168.1.9:27023
    13:45:31.782 logback [main] DEBUG org.mongodb.driver.protocol.command - Command execution completed
    total:3



  • 相关阅读:
    Legendary Items-微软2017实习生笔试第一题
    (转载)华为离职副总裁徐家骏:年薪千万的工作感悟
    【AtCoder Regular Contest 092】C.2D Plane 2N Points【匈牙利算法】
    poj 2236【并查集】
    poj 2431 【优先队列】
    poj 3280【区间dp】
    uva 10453 【回文串区间dp】
    uva 10739【基础(区间)dp】
    poj 2385【动态规划】
    poj 2229 【完全背包dp】【递推dp】
  • 原文地址:https://www.cnblogs.com/sweetchildomine/p/7808995.html
Copyright © 2011-2022 走看看