最近在做订单汇总、商品汇总等等查询,mongo 以前用的不多,最近研究的一点东西,记录一下
javabean
订单详情明细类(包含商品信息)
@Data
@Document(collection = "order_info")
public class OrderMongoEntity extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@Id
private String id;
/**
* 门店 id
*/
@Field("sid")
private Integer sid;
//***省略字段
/**
* 创建时间
*/
@Field("create_time")
private Long createTime;
//***省略字段
/**
* 订单状态
*/
@Field("order_status")
private OrderStatusEnum orderStatus;
/**
* 品列表
*/
@Field("products")
private List<ProductEntity> products;
@Data
public static class ProductEntity implements Serializable {
private int pid;
private String productsDetail;
private int num;
private BigDecimal price;
public <T> T getT(Class<T> tClass) {
return JSON.parseObject(productsDetail, tClass);
}
}
}
聚合后返回的类
@Data
@EqualsAndHashCode(callSuper = true)
public class OrderAggregateStatisticsEntity extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
//因为分组是多条件 这个地方会有很多数据 用 Object 接收就可以 这个数据不需要用
private Object id;
private long count;
private int sid;
private int pid;
private String day;
}
mongoTemplate 查询
//查询条件,个人习惯这样写,请勿对比
List<Criteria> where=new ArrayList<>();
where.add(Criteria.where("create_time").gte(start).lt(end));
// where.add(Criteria.where("order_status").is(OrderStatusEnum.Complete));
// 子集合查询
// 因为 operations.add(Aggregation.unwind("products"))的存在 可以直接写 products.pid
// 如果没有unwind 需要 elemMatch 没有测试 所以这里不多说
where.add(Criteria.where("products.pid").is(18955));
List<AggregationOperation> operations = new ArrayList<>();
operations.add(Aggregation.match(new Criteria().andOperator(where.toArray(Criteria[]::new))));
//把所有需要查询的字段在这里列出来 注意这里的字段是 javabean 的字段
// createTime 转换成 2020-12-12 并且加了 8个小时
// as("day") 是给字段起一个别名
operations.add(Aggregation.project( "sid", "products","createTime")
.andExpression("{$dateToString: {date: { $add: {'$create_time', [0]} }, format: '%Y-%m-%d'}}", new Date(0)).as("day"));
//unwind 我的理解是 list变成单条返回
//去除 list
operations.add(Aggregation.unwind("products"));
//需要分组的字段名
List<String> group = new ArrayList<>();
group.add("day");
group.add("sid");
group.add("products.pid");
// group 分组
// first("day").as("day") first 把第一个 day 的值取出来重名 as 成新字段 day
//first("products.pid").as("pid") 同样的意思 只是这个是子集合的
operations.add(Aggregation.group(group.toArray(String[]::new)).sum("products.num").as("count")
.first("day").as("day")
.first("products.pid").as("pid")
.first("sid").as("sid"));
// 需要返回的字段名字 这里是 as 后的名字
operations.add(Aggregation.project( "pid","day","sid","count"));
// 正常排序
operations.add(Aggregation.sort(Sort.by(Sort.Direction.DESC, "count")));
//查询
AggregationResults<OrderAggregateStatisticsEntity> Results = mongoTemplate.aggregate(Aggregation.newAggregation(operations), OrderMongoEntity.class, OrderAggregateStatisticsEntity.class);
//输出
System.out.println(">>>>>" + JSON.toJSONString(Results.getMappedResults()));
欢迎讨论谢谢!!!
参考1 https://blog.csdn.net/weixin_46114677/article/details/109805644
参考2 https://blog.csdn.net/pengjunlee/article/details/106992249