添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

聚合方法:

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;
                                    有时候在操作mongodb数据库时需要找出某个字段的最大值和最小值,网上的方法就两种,一种是先排序,按升序或者按降序,然后取第一个值就可以得到最大值或最小值了,听起来很美好,但一旦数据库内数据非常多的时候,而且还是mongoDB这样的数据库,如果查一遍库才能拿到值,代价是非常大的。所以我主要采用第二种方法,也就是利用mongodbTemplate来进行管道操作来获取mongodb数据库中某一个或多个字段的最大值和最小值。
                                    1. MongoDB 聚合管道简介
使用聚合管道可以对集合中的文档进行变换和组合,常用于多表关联查询、数据的统计。
db.COLLECTION_NAME.aggregate() 方法用来构建和使用聚合管道,下图是官网给的实例,可以看出来聚合管道的用法还是比较简单的。
2. MongoDB Aggregation 管道操作符与表达式
常用的管道操作符有以下这些:
MySQL 和 MongoDB 的聚合对比:
管道操作符作为“键”,所对应的“值”叫做管道表达式,如 {$match:{status:”A”}},$match 称为管道操作符,而 status:”A”称为管道表达式,每
 public int syncTotal(Date startTime, Date endTime) {
        int result = 0;
        Criteria criteria = new Criteria().andOperator(Criteria.where("data_time").gte(startTime), Criteria.where("data_time").lte(endTime));
        //创建aggreation
                                    1.应用场景
mongodb数据库有一张职位搜索表(t_position_search),里面存储里一些冗余数据(存在一些数据除了id不同其余字段都相同的数据),其中有一个字段是postId,我的需求是在多个相同postId的数据中我只取其中一条(任意一条无所谓,因为相同postId的数据中除了id不同其余字段都相同,我不需要id字段,所以取任意一条无所谓),此时就需要用到mongoTempla...
1.聚合的表达式
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。
下表展示了一些聚合的表达式:
表达式描述实例
计算总和。
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial...
                                    Criteria.where("source").ne(null).exists(true).and("operation_name").in(patterns);
/**source 字段必须存在,且不为空, 匹配in 条件**/
                                    语法:aggregate([{$group:{_id:"$要分组的字段",分组函数处理后的数据名:{分组函数:"执行分组函数的字段"}}}])(6).$addToSet:把值加入数组中,若存在重复则不添加。(4).$first/$last:分组的第一条/最后一条数据。(5).$push:把值加入数组中,允许存在重复。(3).$min/$max:求最小/大值。(2).$avg:求平均值。(2) 不展示该字段:0。6.集合合并:$merge。(1) 展示该字段:1。(1).$sum:求和。
                                    可以通过以下声明方式进行使用
TypedAggregation<User> agg = Aggregation.newAggregation(User.class);AggregationResults<BasicDBObject> aggregationResults = mongoTemplate.aggregate(agg, BasicDBObject.class);  //BasicDBOb