1. 程式人生 > 實用技巧 >Springboot-mongoTemplate踩坑之旅(一.BigDecimal,聚合查詢,排序,最值)

Springboot-mongoTemplate踩坑之旅(一.BigDecimal,聚合查詢,排序,最值)

BigDecimal使用mongoTemplate.save儲存進資料庫的是字串型別,排序會出現問題,兩種解決方式,
1.Query物件自定義collation
重新設定預設的collation屬性.collation({"locale": "zh", numericOrdering:true})再排序。
語句如下:
db.getCollection(集合名稱).find({}).collation({"locale": "zh", numericOrdering:true}).sort({"realTimeConsume":-1});
這樣排序就按照數值來排序,就OK了。
2.配置轉換器

法一有個弊端,在使用聚合查詢的時候,無法配置,這裡記錄下法二,以及聚合查詢方式

法二:
import org.bson.types.Decimal128;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;

import java.math.BigDecimal;

@ReadingConverter
@WritingConverter
public class BigDecimalToDecimal128Converter implements
Converter<BigDecimal, Decimal128> { public Decimal128 convert(BigDecimal bigDecimal) { return new Decimal128(bigDecimal); } }
import org.bson.types.Decimal128;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter; import java.math.BigDecimal; @ReadingConverter @WritingConverter public class Decimal128ToBigDecimalConverter implements Converter<Decimal128, BigDecimal> { public BigDecimal convert(Decimal128 decimal128) { return decimal128.bigDecimalValue(); } }
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.convert.*;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;

import java.util.ArrayList;
import java.util.List;

/**
 * @program: 農事雲
 * @description: 芒果DBhepper配置項
 * @Author: Zhangyb
 * @CreateDate: 15:37
 * @UpdateUser:
 * @UpdateDate
 * @UpdateRemark:
 * @Version: 1.0
 */

@Configuration
//@ComponentScan(basePackages = {"com.bysk.base.mongodb"}) // 將芒果DB注入Spring
public class MongoConfig  {
    @Autowired
    private MongoDatabaseFactory mongoDatabaseFactory;

    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoMappingContext mongoMappingContext) {
        mongoMappingContext.setAutoIndexCreation(true);
        mongoMappingContext.afterPropertiesSet();
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDatabaseFactory);
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext);
        // 此處是去除插入資料庫的 _class 欄位
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        List<Object> list = new ArrayList<>();
        list.add(new BigDecimalToDecimal128Converter());//自定義的型別轉換器
        list.add(new Decimal128ToBigDecimalConverter());//自定義的型別轉換器
        converter.setCustomConversions(new MongoCustomConversions(list));
        return converter;
    }

    @Bean
    public MongoMappingContext mongoMappingContext() {
        //必須重新注入
        MongoMappingContext mappingContext = new MongoMappingContext();
        return mappingContext;
    }

}

注意;MongoMappingContext 必須手動注入,否則會失敗。

業務需求,採集器所有欄位進行求均值

程式碼實現

        //機構id
        Criteria criteria = null;
        if (startTime!=null){
            criteria= Criteria.where(QueryConst.DEVICE_ID)
                    .gte(LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATETIME_PATTERN))
                    .lte(LocalDateTimeUtil.format(endTime, DatePattern.NORM_DATETIME_PATTERN));
        }
        //指定裝置id
        if (deviceId!=null){
            criteria=criteria.and(QueryConst.DEVICE_ID).is(deviceId);
            //構建聚合查詢求AVG
            MatchOperation match = Aggregation.match(criteria);
            List<AggregationOperation> operations=new ArrayList<>();
             operations = mgdbDeviceMonitorRecordService.avgForFiled(MgdbDeviceMonitorRecord.class, QueryConst.EQUIPMENT_ID, operations);
            Aggregation agg = Aggregation.newAggregation(operations);
            AggregationResults<MgdbDeviceMonitorRecord> aggregate = mgdbDeviceMonitorRecordService.getMongoTemplate()
                    .aggregate(agg, MgdbDeviceMonitorRecord.class, MgdbDeviceMonitorRecord.class);
            Document rawResults = aggregate.getRawResults();
        }

    public List<AggregationOperation>  avgForFiled(Class<T> t,String groupFiled,List<AggregationOperation> operations) {
        Field[] fields = t.getDeclaredFields();
        String[] strArray=new String[fields.length];
        GroupOperation group = Aggregation.group(groupFiled);
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            try {
                String name = fields[i].getName();
                System.err.println(name);
                //排除不需要的欄位
                strArray[i]=name;
                group=group.avg(name).as(name);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        operations.add(group);
        return operations;
    }