mongoDB聚合查询实现多表联查,类型转换,返回指定参
数。
查询场景
mongodb 字段的参数类型不⼀致不能进⾏联查的,⽐如,id默认为ObjectId,另外⼀张表存的id为String类型,这时候不可以联查;⽐如存的数据是BigDecimal类型,那么java⾥聚合查询sum也是不可以的。所以如果表之间,或者构造器构造的字段与数据库的字段类型不⼀致,那么数据是查不出的。
数据结构
从表1(车牌表)
@Data
public class Truck{
@Id
protected String id;
/**
* 运输公司ID(主表id)
*
* @notExist
*/
private String transportId;
/**
* 车牌号
*
* @condition
* @notExist聂元梓的大字报
*/
private String truckNo;
/**
* 创建时间
*
* @notView
*/
private String createTime;
/**小学三年级同步英语
* 运输单位(关联表的字段)
*/
private String unitName;
/**
* 邀请码(关联表的字段)
*/
private String inviteCode;
}
我只显⽰关键字段,多余字段不展⽰,这次处理的是三表联查。上边这个表是从1表,不是主表,把它放在第⼀个是因为这个表是作为返回使⽤的。
从表2(邀请码表)
注:邀请⼈员进⼊运输单位的表,⽆需关注我的实际业务。
/**
* 邀请码管理
* @access=inviteCode
* @parent=appcommon
* @parentName=⽇常业务管理
*/
@Data
public class InviteCode{
@Id
protected String id;
/**
* 邀请码
* @condition
* @notExist
*/profiteer
private String code;
/**
* 所属运输单位id
*/
private String belongTransportId;
}
晒黑后快速美白方法主表(运输单位表)
/**
* 运输单位
*/
@Data
public class TransportUnit{
@Id
protected String id;
/**
* 单位名称
*
* @condition
* @notExist
*/
private String unitName;
/**
* 创建⼈(邀请⼈)
*
* @notView
*/
private String creator;
}
三个表我去了⼀些没⽤的内容,保留了三表联查的关键字段。英语免费在线翻译
ca939
mongoDB sql语句实现
从表结构中可以看出,运输单位表作为主表需要关联其他俩个表。从返回表⾥可以看到我们想要返回内容。
要注意⼀点的是,为啥以运输单位作为主表,不仅仅是因为主id在这个表中,⽽且ObjectId转String好转换,反之处理⽐较⿇烦。
{
$project: {
id: {
$toString: "$_id"
},
unitName: 1,
}
},
{
$lookup:
{
from: "truck",
localField: "id",
foreignField: "transportId",
as: "truck"
}
},
{
$unwind: "$truck"
},
{
$lookup:
{
from: "inviteCode",
localField: "id",
foreignField: "belongTransportId",
as: "inviteCode"
}
},
{
$unwind: "$inviteCode"
},
{
$project:{
title:1,
truck:{
unitName:"$unitName",
truckNo:1,
code: '$de',
transportId:1,
creator: 1,
createTime: 1,
}
}
},
bnp]);
解释⼀下sql,
1. 第⼀个lookup后使⽤了unwind将单个Bson拆为Bson数组,这点不可缺少,不然第⼆层lookup会关联不上。
2. 这⾥使⽤了project来将ObjectId转为String,当然也是通过这个返回指定字段的。
3. 因为之前使⽤了unwind,最后使⽤了group再进⾏⼀次压缩聚合。
查询结果:
Java实现
public PageInfo<Truck> findAllByLike(Truck truck, int page, int size) throws GenericException {
String truckNo = TruckNo();
String transportName = TransportName();
Criteria criteria;
criteria = Criteria.where("id").not();
if (StringUtils.isNotEmpty(truckNo)){
criteria.and("truckNo").regex(truckNo);
}
if (StringUtils.isNotEmpty(transportName)){
criteria.and("unitName").regex(transportName);
}
Aggregation agg = wAggregation(
project("id").andExpression("toString(_id)").as("id")
.and("unitName").as("unitName"),
lookup(Fields.field("truck"),Fields.field("id"),Fields.field("transportId"),Fields.field("truck")), unwind("truck"),
lookup("inviteCode","id","belongTransportId","inviteCode"),
2012年奥斯卡unwind("inviteCode"),
project("unitName")
.and("ansportId").as("transportId")
.and("de").as("inviteCode")
.and("ator").as("creator")
.and("ateTime").as("createTime")
.and("uckNo").as("truckNo"),
match(criteria),
skip((page)*size),
limit(size)
approvement);
Aggregation agg1 = wAggregation(
project("id").andExpression("toString(_id)").as("id")
.and("unitName").as("unitName"),
lookup(Fields.field("truck"),Fields.field("id"),Fields.field("transportId"),Fields.field("truck")), unwind("truck"),
lookup("inviteCode","id","belongTransportId","inviteCode"),
unwind("inviteCode"),
project("unitName")
.and("ansportId").as("transportId")
.and("de").as("inviteCode")
.and("ator").as("creator")
.and("ateTime").as("createTime")
.and("uckNo").as("truckNo"),
match(criteria)
);
AggregationResults<Truck> results = mongoTemplate.aggregate(agg,
"transportUnit", Truck.class);
明尼苏达大学排名
AggregationResults<Truck> results1 = mongoTemplate.aggregate(agg1,
"transportUnit", Truck.class);
List<Truck> trucks = MappedResults();
List<Truck> mappedResults = MappedResults();
PageInfo<Truck> pageInfo = new PageInfo<>(trucks);
pageInfo.tTotal(mappedResults.size());
return pageInfo;
}
这⾥有个问题,就是聚合查询,分页的情况下⽆法返回总条数,所以得通过相同的条件,部分也单独查⼀次总条数。注意:match查询条件必须放查询联查之后,好⽐sql where条件放查询结果之后。
另外⼀种⽅式查询
不使⽤project的⽅式查询进⾏类型转换⽐较⿇烦,使⽤addFields也可以实现。
sql: