MONGODB04 - 資料聚合Aggregation進階之lookup和unwind組合實現關聯查詢
阿新 • • 發佈:2020-11-06
前因
最近專案上又新需求了,相關的統計資訊介面,需要在MongoDB中實現類似mysql多表關聯查詢,那麼問題來了,MongoDB要如何才能像Hibernate那樣一對一,一對多對映關係了?本節講藉助loopup和unwind組合方式來實現此功能
需求
-
以勳章任務為主表查詢勳章任務名稱及相關配置資訊
-
匯出每個人任務下對應的檔案結果對比資訊
備註:涉及文件 Medal(勳章)、MedalTask(勳章任務)、MedalTaskFile(任務明細),文件從左到右一對多關係
實現
之前版本
實現思路
-
分頁查詢MedalTask,取出MedalId集合和taskIds集合
-
分別從Medal和MedalTaskFile查詢資料集合,進行二次聚合
Aggregation進階之lookup
先貼程式碼
/*資料聚合*/ Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(criteria), /*關聯勳章*/ Aggregation.lookup("medal", "medalId", "_id", "medal"), /*關聯任務*/ Aggregation.lookup("medalTaskFile", "_id", "medalTaskId", "taskFiles"), /*查詢起始值*/ Aggregation.skip(params.getPageNum() > 1 ? (params.getPageNum() - 1) * params.getPageSize() : 0), /*分頁大小*/ Aggregation.limit(params.getPageSize()), /*排序*/ Aggregation.sort(Sort.by(Sort.Order.desc("createdTime"))), /*打散Medal*/ Aggregation.unwind("medal") ); List<MedalUserTo> medalUserTos = medalV4MongoTemplate.aggregate(aggregation, MedalTask.class, MedalUserTo.class).getMappedResults();
@Data
private class MedalUserTo {
private String medalId;
private String userId;
private Integer status;
private Double rate;
private Instant createdTime;
private Instant submitTime;
private Medal medal;
private List<MedalTaskFile> taskFiles;
}
方法解讀
方法 | 引數 | 備註 |
---|---|---|
match() | (Criteria criteria) | 查詢條件構建 |
lookup() | (String from, String localField, String foreignField, String as) | from:關聯表localField:主記錄關聯欄位,傳入的是MongoDB中的欄位名,非實體類欄位名foreignField:關聯表關聯欄位,欄位名同上as:別名,及實體類對映欄位名(lookup預設返回的型別是ArrayList,相關的欄位接收預設需要使用集合接收,類似一對多這種對映關係) |
skip() | (int elementsToSkip)(long elementsToSkip) | 查詢起始值 |
limit() | (long maxElements) | 最大element數量,及分頁大小 |
sort() | (Sort sort) | 排序欄位 |
unwind() | (String field) | 展開這個欄位主要是用於聚合記錄拆分,把對應的集合欄位(長度為n)對應的主記錄拆分n個物件,欄位名對應是集中中單個文件物件本段程式碼使用場景,在已知一對一場景下,把lookup關聯的物件由陣列程式設計單物件(注:若不是一對一關係,則可能出現重複物件),所以在MedalUserTo中可以使用Medal物件接收該引數 |
project() | (String... fields) | 控制顯示查詢欄位,可用於返回指定欄位 |
unwind和project在MongoDB組合查詢示例
正常查詢
//正常記錄查詢,這裡遮蔽相關欄位,主要看資料結構
db.operationLog.aggregate([
{$match:{_id:'DBDF7FA8C72C4606A15CF250FF35A530'}},
{$project:{_id:1,batchIdList:1}}
])
結果
{
"_id" : "DBDF7FA8C72C4606A15CF250FF35A530",
"batchIdList" : [
{
"taskId" : "721EB7250C0049B49A5AB4A734498F2B",
"batchInfos" : {}
},
{
"taskId" : "E1C60CAD114D405B916E66A05256C07B",
"batchInfos" : {}
}
]
}
使用unwind拆分查詢記錄
db.operationLog.aggregate([
{$match:{_id:'DBDF7FA8C72C4606A15CF250FF35A530'}},
{$unwind:"$batchIdList"}
])
結果
{
"_id" : "DBDF7FA8C72C4606A15CF250FF35A530",
"batchIdList" : {
"taskId" : "721EB7250C0049B49A5AB4A734498F2B",
"batchInfos" : {}
}
}
{
"_id" : "DBDF7FA8C72C4606A15CF250FF35A530",
"batchIdList" : {
"taskId" : "E1C60CAD114D405B916E66A05256C07B",
"batchInfos" : {}
}
}
對Aggregation的group、lookup、project和unwind方法進行靈活組合,大大精簡了我們對MongoDB的關聯查詢、統計查詢及相關聚合查詢等操作程式碼編寫