mongoTemplate.aggregate() 聚合查询,关联查询

聚合方法实现了什么功能

条件查询,分组,统计,关联查询,排序,分页,返回指定字段

聚合方法:

AggregationResults<DocumentEntity> results = mongoTemplate.aggregate(aggregation, TableNameUtils.getDocTableName(request.getCompanyId()), DocumentEntity.class);

源码:
@Override
public <O> AggregationResults<O> aggregate(Aggregation aggregation, String collectionName, Class<O> outputType) {
   return aggregate(aggregation, collectionName, outputType, null);
}
参数1:Aggregation,看下这个对象的方法,可以看到入参有两种,集合/数组

public static Aggregation newAggregation(List<? extends AggregationOperation> operations) {
   return newAggregation(operations.toArray(new AggregationOperation[operations.size()]));
}

public static Aggregation newAggregation(AggregationOperation... operations) {
   return new Aggregation(operations);
}

1,关联查询

需求:有三张表,档案表,发票表,文件表,发票表和文件表通过字段文档流水号(documentSerialNum),与档案表字段(serialNum)流水号关联,现在要根据serialNum查询文档表及其下面的发票和发票信息(1:n)。

代码:

private List<DocumentEntity> getDocumentEntities(BaseRequestModel request, List<String> serialNumS) {
    // 文件和发票表通过外键查询
    LookupOperation lookupOperation = LookupOperation.newLookup().
            from("table_file").
            localField("serialNum").
            foreignField("documentSerialNum").
            as("docs");
    LookupOperation lookupOperationinv = LookupOperation.newLookup().
            from("table_inv").
            localField("serialNum").
            foreignField("documentSerialNum").
            as("docs2");

    // 拼装具体查询信息
    Criteria docCri = Criteria.where("docs").not().size(0);
    docCri.and("serialNum").in(serialNumS);
    docCri.and("isDel").is(IsDelEnum.NO.getValue());
    docCri.and("docs.isDel").is(IsDelEnum.NO.getValue());
    docCri.and("docs2.isDel").is(IsDelEnum.NO.getValue());
    AggregationOperation match = Aggregation.match(docCri);

    // 把条件封装成List
    List<AggregationOperation> operations = new ArrayList<>();
    operations.add(lookupOperation);
    operations.add(lookupOperationinv);
    operations.add(match);
    
    // 构建 Aggregation 
    Aggregation aggregation = Aggregation.newAggregation(operations);

    // 执行查询
    AggregationResults<DocumentEntity> results = mongoTemplate.aggregate(aggregation, "table_doc", DocumentEntity.class);

    // 或者入参为数组
    Aggregation aggregation = Aggregation.newAggregation(lookupOperation,lookupOperationinv,Aggregation.match(docCri));

    return results.getMappedResults();
}

特别注意的一点:主字段和外键对应哪个表,指的是mongoTemplate.aggregate(),方法中的表

localField:table_doc主字段 serialNum

foreignField:table_inv table_file 外键 documentSerialNum

LookupOperation lookupOperation = LookupOperation.newLookup(). from("table_file"). localField("serialNum"). foreignField("documentSerialNum"). as("docs");

2,返回指定字段,分组,统计,排序,分页

详细见原文:

https://www.jianshu.com/p/78b96ca40927

https://www.cnblogs.com/wslook/p/9831842.html

需求:在订单表中,根据buyerNick分组,统计每个buyerNick的电话、地址、支付总金额以及总商品数,返回结果是CustomerDetail。

/*
 * project:列出所有本次查询的字段,包括查询条件的字段和需要搜索的字段;
 * match:搜索条件criteria
 * unwind:某一个字段是集合,将该字段分解成数组
 * group:分组的字段,以及聚合相关查询
 *      sum:求和(同sql查询)
 *      count:数量(同sql查询)
 *      as:别名(同sql查询)
 *      addToSet:将符合的字段值添加到一个集合或数组中
 * sort:排序
 * skip&limit:分页查询
 */
public List<CustomerDetail> customerDetailList(Integer pageNum,String userId,String buyerNick,String itemId,List<String> phones) throws Exception{
    Criteria criteria = Criteria.where("userId").is(userId);
    Integer pageSize = 10;
    Integer startRows = (pageNum - 1) * pageSize;
    if(buyerNick != null && !"".equals(buyerNick)){
        criteria.and("buyerNick").is(buyerNick);
    }
    if(phones != null && phones.size() > 0){
        criteria.and("mobile").in(phoneList);
    }
    if(itemId != null && !"".equals(itemId)){
        criteria.and("orders.numIid").is(itemId);
    }
    Aggregation customerAgg = Aggregation.newAggregation(
            Aggregation.project("buyerNick","payment","num","tid","userId","address","mobile","orders"),
            Aggregation.match(criteria),
               Aggregation.unwind("orders"),
            Aggregation.group("buyerNick").first("buyerNick").as("buyerNick").first("mobile").as("mobile").
            first("address").as("address").sum("payment").as("totalPayment").sum("num").as("itemNum").count().as("orderNum"),
            Aggregation.sort(new Sort(new Sort.Order(Sort.Direction.DESC, "totalPayment"))),
            Aggregation.skip(startRows),
            Aggregation.limit(pageSize)
            );
    List<CustomerDetail> customerList = tradeRepository.findAggregateList(new Query(criteria), userId, customerAgg,CustomerDetail.class);
    return customerList;
}
public <T> List<T> findAggregateList(Query query,String userNickName, Aggregation aggregation,Class<T> clazz) {
    AggregationResults<T> aggregate = this.mongoTemplate.aggregate(aggregation, collectionName, clazz);
    List<T> customerDetails = aggregate.getMappedResults();
    return customerDetails;
}

3,三张表在java中实体如何关联的:字表定义为List

@Data
@ToString
public class DocumentEntity extends MongoBaseEntity {

    /**
     * 档案名称
     */
    private String name;
    /**
     * 档案类型
     */
    private int type;
    /**
     * 所属公司
     */
    private Integer companyId;

    /**
     * 流水号
     */
    private String serialNum;
    /**
     * 档案编号
     */
    private String code;
    /**
     * 状态
     */
    private String status;
    /**
     * 保密等级
     */
    private String secrecyLevel;
    /**
     * 资料数量
     */
    private Long detailNum;
    /**
     * 描述
     */
    private String description;
    /**
     * 自定义字段 map集合,
     */
    private Map<String,Object> documentMap;

    /**
     * 文件集合
     */
    private List<FileEntity> fileList;
    /**
     * 发票集合
     */
    private List<InvoiceEntity> InvoiceList;


}

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值