我在项目中使用mongodb和spring-boot。我使用手册参考指出了一个集合,我的结构就像下面这样。
卷盘收集
{ _id : "reel_id_1", name: "reel 1", category :[ { _id : "category_id_1", name: "category 1", videos: ["video_id_1","video_id_2"] } ] }
影片集
{ _id: "video_id_1", // first document name: "mongo" } { _id: "video_id_2", // seconddocument name: "java" }
Java类是
@Document @Data public class Reel { @Id private ObjectId _id; private String name; List<Category> category; } @Data public class Category { @Id private ObjectId _id=new ObjectId(); private String name; Video videos; } @Document @Data public class Video { @Id private ObjectId _id = new ObjectId(); private String name; }
我试图通过mongoTemplate加入两个文档
public List<Reel> findById(ObjectId _id) { LookupOperation lookupOperation = LookupOperation.newLookup() .from("video") .localField("category.videos") .foreignField("_id") .as("category.videos"); UnwindOperation unwindOperation = Aggregation.unwind("category"); Aggregation agg = newAggregation(unwindOperation,match(Criteria.where("_id").is(_id)),lookupOperation); Aggregation aggregation = newAggregation(lookupOperation); List<Reel> results = mongoTemplate.aggregate(aggregation, "reel", Reel.class).getMappedResults(); return results; }
但这会引发错误。
Failed to instantiate java.util.List using constructor NO_CONSTRUCTOR with arguments
但是由于使用“ unwind”,所以创建了一个新的Entity UnwindReel 并添加Category category而不是List<Category> category。和二手
Category category
List<Category> category
List<UnwindReel> results = mongoTemplate.aggregate(aggregation, "reel", UnwindReel.class).getMappedResults();
它仅合并第一个视频(video_id_1)对象。如何获取 视频数组中的 所有对象?有什么方法可以提取吗?有人可以让我知道我在这里错过了什么吗?提前致谢。
您存储在数据库中的JSON结构错误。您的Reel课程需要的列表Category,但在数据库中您已存储为嵌套对象。
Reel
Category
您需要在之后添加此阶段 $lookup
$lookup
{ "$addFields": { "category": { "$map": { "input": "$category.videos", "in": { "videos": "$$this" } } } } }
public List<Reel> findById(String _id) { Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(Criteria.where("_id").is(_id)), Aggregation.lookup(mongoTemplate.getCollectionName(Video.class), "category.videos", "_id", "category.videos"), new AggregationOperation() { @Override public Document toDocument(AggregationOperationContext context) { return new Document("$addFields", new Document("category", new Document("$map", new Document("input", "$category.videos") .append("in", new Document("videos", "$$this"))))); } }) .withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build()); LOG.debug( aggregation.toString().replaceAll("__collection__", mongoTemplate.getCollectionName(Reel.class))); return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Reel.class), Reel.class) .getMappedResults(); }
mongoTemplate.getCollectionName
{allowDiskUse: true}