[英]MongoDB with Java async driver: $lookup always empty
我有以下兩個“鏈接的” POJO實體:
public class User {
public ObjectId id; // this is mapped to "_id" in the MongoDB
public String userName;
...
}
public class Purchase {
public ObjectId id; // this is mapped to "_id" in the MongoDB
public ObjectId userId;
public transient User user;
public String productTitle;
...
}
想法是僅使用$ lookup聚合函數按需持久保存UserId以進行購買和加載(或:JOIN)相應的User文檔。 由於Purchase.user屬性不能被保存在MongoDB中,它被聲明為瞬態。 能行嗎?
現在,在我的PurchaseRepository中,我試圖像這樣實現它:
public void getSinglePurchaseWithUser(Bson filter, SingleResultCallback<Purchase> callback) {
Document match = new Document("$match", filter);
Document lookupFields = new Document("from", "Users");
lookupFields.put("localField", "userId");
lookupFields.put("foreignField", "_id");
lookupFields.put("as", "user");
Document lookup = new Document("$lookup", lookupFields);
List<Document> pipeline = Arrays.asList(match, lookup);
AggregateIterable<Purchase> output = this.collection.aggregate(pipeline);
output.first(callback);
}
不幸的是,purchase.user在結果中始終為空。 我還嘗試手動投影以明確地讀取用戶:
Document projectFields = new Document("_id", 1);
projectFields.put("userId", 1);
projectFields.put("user", "$user");
...
Document project = new Document("$project", projectFields);
List<Document> pipeline = Arrays.asList(match, lookup, project);
但這會引發錯誤讀取:
org.bson.codecs.configuration.CodecConfigurationException:使用AutomaticPojoCodec解碼時發生異常。 解碼為“購買”失敗,但有以下例外:
無法解碼“用戶”。 僅在CurrentBSONType為DOCUMENT時才能調用readStartDocument,而在CurrentBSONType為ARRAY時不能調用。
自定義編解碼器或PojoCodec可能需要顯式配置和注冊以處理此類型。
我想念什么?
得到它了。
第一個錯誤是“ as”字段必須是一個數組:
指定要添加到輸入文檔中的新數組字段的名稱。 新數組字段包含from集合中的匹配文檔。 如果輸入文檔中已經存在指定的名稱,則現有字段將被覆蓋。
另一個問題是transient
屬性既不會序列化也不會反序列化。 一種解決方法是將吸氣劑標記為@BsonIgnore,而不是setter。 這樣,該屬性在序列化時被跳過,而在反序列化時不被跳過。
public class Purchase {
private User user;
public ObjectId userId;
@BsonIgnore
public OrgenicUser getUser() {
return this.user;
}
public void setUser(OrgenicUser value) {
this.user = value;
}
}
如果要像我這樣將數組限制為一個對象,可以在$getElemAt
中使用$getElemAt
來拉出第一個條目,如下所示:
Document lookupFields = new Document("from", from);
lookupFields.put("localField", localField);
lookupFields.put("foreignField", foreignField);
lookupFields.put("as", as);
Document lookup = new Document("$lookup", lookupFields);
// pulls the first match from the localField array
Document firstMatch = new Document(as, new Document("$arrayElemAt", Arrays.asList("$" + as, 0)));
// keep all fields and add/update the specified field
Document project = new Document("$addFields", firstMatch);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.