Mongodb 關聯表查詢

Awbeci發表於2021-09-26

前言

最近學習使用mongodb中間使用關聯表查詢問題遇到一些問題記錄下來分享給大家。

mongodb關聯查詢

之前使用SQL語法來查詢oracle、sqlserver、mysql表之間的關聯,但是到mongodb之後完全無從下手,寫法完全不一樣,於是到網上查詢mongodb關聯表查詢的寫法,於是參考程式碼自己試著寫了下,但是發現有好多問題,比如我有兩個表user和apple,

user表:

idnameagecreateDt
ObjectId(1xxxx1)zhangsan32
ObjectId(2xxxx2)lishi23
ObjectId(3xxxx3)wangwu19
ObjectId(4xxxx4)liuliu28

apple表:

iduiddevicecreateDt
ObjectId(axxxxa)1xxxx110
ObjectId(bxxxxb)2xxxx22
ObjectId(cxxxxc)3xxxx37
ObjectId(dxxxxd)4xxxx41

user實體類:

@Setter
@Getter
public class User {
    private String id;
    private String name;
    private Integer age;
    private Date createDt;
}

apple實體類:

@Setter
@Getter
public class Apple {
    private String id;
    private String uid;
    private Integer device;
    private Date createDt;
}

user和apple之間是一對一關係,現在我的查詢要求是:按device數量從大到小排序查詢使用者資料。

查詢結果應該是:

idnameagecreateDt
ObjectId(1xxxx1)zhangsan32
ObjectId(3xxxx3)wangwu19
ObjectId(2xxxx2)lishi23
ObjectId(4xxxx4)liuliu28

我們分別使用user表和apple表做主表來查詢,那麼使用mongodb語法我們試著來寫一下。

以user表做主表查詢

// 1、新增_id欄位型別轉換
AddFieldsOperation addFieldsOperation = AddFieldsOperation.addField("_id").withValue(ConvertOperators.ToString.toString("$_id")).build();

// 2、按引數順序:被關聯表apple,主表user.id,被關聯表apple.uid,別名
LookupOperation lookupOperation = Aggregation.lookup("apple", "_id", "uid", "apple_as");

// 3、查詢哪些欄位,類似sql裡面的 select 選擇器
ProjectionOperation project = Aggregation.project("name","age","createDt").and("apple_as.device").as("device");

// 4、按照apple.device數量排序
// 注意:不能使用apple_as.device,並且 device欄位必須出現在project裡面,否則查詢失敗
SortOperation sort = Aggregation.sort(Sort.Direction.DESC, "device");

// 5、新增取List中
List<AggregationOperation> operationList = Lists.newArrayList();
operationList.add(addFieldsOperation);
operationList.add(lookupOperation);
operationList.add(project);
operationList.add(sort);
Aggregation agg = Aggregation.newAggregation(operationList);

// 因為返回的是User實體類,所以不會出現device欄位,你可以使用Map.class來返回想要的欄位
AggregationResults<User> aggregationResults = mongoTemplate.aggregate(agg, "user", User.class);
// 6、返回關聯查詢結果
List<User> dataList = aggregationResults.getMappedResults();

注意:我們在查詢之前要把主表的id轉換成String型別,因為被關聯表的uid就是String型別,否則查詢失敗

以apple表做主表查詢

// 1、新增uid欄位型別轉換
AddFieldsOperation addFieldsOperation = AddFieldsOperation.addField("uid").withValue(ConvertOperators.ToObjectId.toObjectId("$uid")).build();

// 2、按引數順序:被關聯表user,主表apple.uid,被關聯表user.id,別名
LookupOperation lookupOperation = Aggregation.lookup("user", "uid", "_id", "user_as");

// 3、查詢哪些欄位,類似sql裡面的 select 選擇器
// 注意:因為user是被關聯表,所以要使用user_as別名的方式來獲取使用者資訊欄位
ProjectionOperation project = Aggregation.project("user_as.name","user_as.age","user_as.createDt","device");

// 4、按照apple.device數量排序
SortOperation sort = Aggregation.sort(Sort.Direction.DESC, "device");

// 5、新增取List中
List<AggregationOperation> operationList = Lists.newArrayList();
operationList.add(addFieldsOperation);
operationList.add(lookupOperation);
operationList.add(project);
operationList.add(sort);
Aggregation agg = Aggregation.newAggregation(operationList);

// 因為返回的是User實體類,所以不會出現device欄位,你可以使用Map.class來返回想要的欄位
AggregationResults<User> aggregationResults = mongoTemplate.aggregate(agg, "apple", User.class);
// 6、返回關聯查詢結果
List<User> dataList = aggregationResults.getMappedResults();

注意:我們在查詢之前要把主表的uid轉換ObjectId型別,因為被關聯表的_id就是ObjectId型別,否則查詢失敗

總結

1、mongodb關聯查詢一定要注意ObjectId型別和String型別之間的轉換,否則不成功
2、project中出現的欄位會影響 sort排序
3、operationList的新增前後順序也會影響查詢
4、如果查詢失敗要多試幾遍,到底是哪一步出現的影響,我也是不斷的試錯才總結出來的。
5、如果有條件的話可以加如下程式碼:

AggregationOperation match = Aggregation.match(Criteria.where("uid").is(uid));
LimitOperation limit = Aggregation.limit(10);

operationList.add(match);
operationList.add(limit);

引用

MongoTemplate聚合(一)$lookup

Mongo學習筆記(三) 通過Aggregation和lookup進行多級關聯查詢

Springboot整合MongoDB系列(五)---LookupOperation關聯查詢

mongoTemplate關聯查詢

Spring Data MongoDB: Projections and Aggregations

Java使用MongoTemplate操作MangoDB,實現根據時間等條件組合查詢,解決ISODate的問題

相關文章