前言
我使用的是spring包里的mongoTemplate进行操作Mongo,那基本单表的操作满足日常需求了;但是难免会有要联表操作的时候,mongo-data包里提供了一种Aggregation 类,可以理解为建立管道。
联表
LookupOperation 这个类就是用来进行联表操作的类,具体方法:
- newLookup ,用来创建一个LookupOperation.Builder;
- from, 要连接哪张表,类似Mysql的JOIN;
- localField,主表哪个字段去连接,指明出来;
- foreignField ,连接的那个表哪个字段关联;
- as, 从表结果集名,最后会在主表多出这个自定义列,默认List;理解为as一个别名,会把从表的数据以数组的形式在as字段内
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("Item")
.localField("sItemId")
.foreignField("_id")
.as("item");
Select列
ProjectionOperation 这个类可以理解为构造Mysql的Select列
ProjectionOperation projectionOperation = Aggregation.project("id", "sItemId", "iCount", "item.iDuration", "item.sName", "item.sIcon", "item.sDes", "item.iItemType");
表结构
Item
{
"_id": "111",
"sActiveId": "222",
"sName": "333",
"sIcon": "444",
"sDes": "555",
"iItemType": NumberInt("1"),
"sValue": "666",
"iProperty": [
"0"
],
"iDuration": NumberInt("77"),
"createTime": ISODate("2022-03-23T08:13:19.694Z"),
"updateTime": ISODate("2022-03-23T08:13:19.694Z"),
"iStatus": NumberInt("0")
}
ItemUser
{
"_id": "222",
"sActiveId": "333",
"sItemId": "111",
"sUserId": "444",
"iCount": NumberInt("4")
}
生成管道
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("Item")
.localField("sItemId")
.foreignField("_id")
.as("item");
Criteria criteria = Criteria.where("sUserId").is("444");
ProjectionOperation projectionOperation = Aggregation.project("id", "sItemId", "iCount", "item.iDuration", "item.sName", "item.sIcon", "item.sDes", "item.iItemType");
Aggregation aggregation = Aggregation.newAggregation(
lookupOperation,
Aggregation.match(criteria),
Aggregation.unwind("item"),
Aggregation.sort(Sort.Direction.DESC, "createTime"),
projectionOperation
);
AggregationResults<JSONObject> aggregationResults = mongoTemplate.aggregate(aggregation, "ItemUser", JSONObject.class);
List<JSONObject> result = aggregationResults.getMappedResults();
前面提到,as会在主表新增个列,列里内容是数组,Aggregation.unwind(“item”)的作用就是把as列里数组拆掉,通过ProjectionOperation 加在主表自定义字段中
|