从mongoDB中的手动参考中查找所有嵌入式文档 [英] Find all embedded documents from manual reference in mongoDB

查看:129
本文介绍了从mongoDB中的手动参考中查找所有嵌入式文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中使用mongodb和spring-boot.我用手工参考指出了一个集合,我的结构就像下面这样.

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

卷筒收藏

{
    _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加入两个文档

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

但是会引发错误.

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

但是由于我使用了"unwind",所以我创建了一个新的实体 UnwindReel 并添加了Category category而不是List<Category> category.并用

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

它仅合并第一个视频(video_id_1)对象.如何在视频数组中获取所有对象?有什么方法可以提取吗?谁能让我知道我在这里错过了什么吗?预先感谢.

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.

推荐答案

您存储在数据库中的JSON结构错误.您的Reel类需要Category的列表,但是在数据库中您已存储为嵌套对象.

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

您需要在$lookup

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

Java代码

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

}

建议

  1. 不要硬编码集合名称,请使用更好的mongoTemplate.getCollectionName方法
  2. 始终在执行之前记录聚合管道,这有助于调试.
  3. 如果您的馆藏将来会增加,请使用{allowDiskUse: true} MongoDb聚合选项.
  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.

这篇关于从mongoDB中的手动参考中查找所有嵌入式文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆