Find all embedded documents from manual reference in mongoDB

╄→гoц情女王★ 提交于 2020-05-09 08:56:36

问题


I use mongodb and spring-boot in a project. I used manual reference to point out a collection, My structure is like follwing.

Reel collection

{
    _id : "reel_id_1",
    name: "reel 1",
    category :[
        {
            _id : "category_id_1",
            name: "category 1", 
            videos: ["video_id_1","video_id_2"]
        }
    ]
}

Video collection

{
    _id: "video_id_1",  // first document
    name: "mongo"
}

{
    _id: "video_id_2",  // seconddocument
    name: "java"
}

Java classes are

@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;

}

I tried to join both document via 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;
}

But it throws an error.

Failed to instantiate java.util.List using constructor NO_CONSTRUCTOR with arguments

But Since I use "unwind", I created a new Entity UnwindReel and add Category category instead of List<Category> category. And used

List<UnwindReel> results = mongoTemplate.aggregate(aggregation, "reel", UnwindReel.class).getMappedResults();

It combines only first video (video_id_1) object. How can I get all objects inside videos array? Is there any method to fetch? and Could anyone please let me know what I missed here? Thanks in advance.


回答1:


Your JSON stored in database has wrong structure. Your Reel class expects list of Category, but in database you have stored as nested object.

You need to add this stage just after $lookup

{
  "$addFields": {
    "category": {
      "$map": {
        "input": "$category.videos",
        "in": {
          "videos": "$$this"
        }
      }
    }
  }
}

Java code

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();

}

Recomendations

  1. Do not hard-code collection name, use better mongoTemplate.getCollectionName method
  2. Always log aggregation pipeline before performing, it helps debugging.
  3. If your collection will grow in the future, use {allowDiskUse: true} MongoDb aggregation option.


来源:https://stackoverflow.com/questions/61161589/find-all-embedded-documents-from-manual-reference-in-mongodb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!