【问题标题】:MongoDB embedded Document Array: Get only one embedded document with a spezific attributeMongoDB 嵌入式文档数组:仅获取一个具有特定属性的嵌入式文档
【发布时间】:2020-11-22 06:05:11
【问题描述】:

我想从带有 mongodb 和 spring boot 的数组中获取一个具有特定字段(版本)的嵌入式文档。 这是数据结构:

{
   "_id": 5f25882d28e40663719d0b52,
   "versions": [
       {
           "versionNr": 1
           "content": "This is the first Version of some Text"
       },
       {
           "versionNr": 2
           "content": "This is the second Version of some Text"
       },
       ...
   ]
   ...
}

这是我的实体:

@Data
@Document(collection = "letters")
public class Letter {
  @Id
  @Field("_id")
  private ObjectId _id;
  
  @Field("versions")
  private List<Version> versions;
}

//There is no id for embedded documents 
@Data
@Document(collection = "Version")
public class Version{

  @Field("content")
  private String content;
  
  @Field("version")
  private Long version;
}

这是不起作用的查询。我认为“加入”是不正确的。但无法找出正确的方法。

public Optional<Version> findByIdAndVersion(ObjectId id, Long version) {
        Query query = new Query(Criteria.where("_id").is(id).and("versions.version").is(version));
        return Optional.ofNullable(mongoTemplate.findOne(query,Version.class,"letters"));
    }
}

编辑:这是一个有效的聚合,我确信它不是一个很好的解决方案,但它有效

@Override
    public Optional<Version> findByIdAndVersion(ObjectId id, Long version) {

        MatchOperation match = new MatchOperation(Criteria.where("_id").is(id).and("versions.version").is(version));
        Aggregation aggregate = Aggregation.newAggregation(
                match,
                Aggregation.unwind("versions"),
                match,
                Aggregation.project()
                        .andInclude("versions.content")
                        .andInclude("versions.version")
        );

        AggregationResults<Version> aggregateResult = mongoTemplate.aggregate(aggregate, "letters", Version.class);
        Version version = aggregateResult.getUniqueMappedResult();
        return Optional.ofNullable(mongoRawPage);
    }

【问题讨论】:

    标签: spring mongodb spring-boot


    【解决方案1】:
    Query query = new Query(Criteria.where("_id").is(id).and("versions.version").is(version));
    return Optional.ofNullable(mongoTemplate.findOne(query,Version.class,"letters"));
    

    您正在查询 Letter 文档,但您的实体类被指定为 Version.class,因为来自 MongoDB 的 findOne 本身不会返回子文档,而是返回整个文档,因此您需要将 Letter.class 作为返回类型和过滤器(项目)要取回哪些字段。因此,您可以投影您想要接收的单个版本子文档,如下所示:

    Query query = new Query()
                .addCriteria(Criteria.where("_id").is(id).and("versions.version").is(version))
                .fields().position("versions", 1);
    Optional.ofNullable(mongoTemplate.findOne(query, Letter.class))
            .map(Letter::getVersions)
            .findFirst()
            .orElse(null);
    

    或使用聚合管道:

    newAggregation(
            Letter.class,
            match(Criteria.where("_id").is(id)),
            unwind("versions"),
            replaceRoot("versions"),
            match(Criteria.where("version").is(version))), 
        Version.class)
    

    注意 -- 我是临时输入的。

    【讨论】:

    • 聚合解决方案无法编译,因为“版本”不是聚合。但根据你的回答,我有另一个聚合。我将我的“解决方案”添加到我的帖子中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 2012-11-18
    • 2011-02-15
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多