You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Morphia中查询PlayerStatisticsData并过滤transactions子数组

查询PlayerStatisticsData并过滤嵌套的PlayerTransaction列表

下面分不同技术栈给出具体实现方案:

一、JPA/Hibernate(关系型数据库场景)

如果你的项目用JPA关联实体(PlayerStatisticsData和PlayerTransaction是一对多关系),可以用以下两种方式过滤嵌套的transactions列表:

1. 自定义DTO+JPQL投影

先创建一个DTO类,用来封装查询结果:

public class PlayerStatsDto {
    private Long id;
    private String playerName; // 替换成你的实际字段
    private List<PlayerTransaction> recentTransactions;

    // 对应JPQL查询的构造函数
    public PlayerStatsDto(Long id, String playerName, List<PlayerTransaction> recentTransactions) {
        this.id = id;
        this.playerName = playerName;
        this.recentTransactions = recentTransactions;
    }

    // getter、setter按需添加
}

然后在Repository中写JPQL查询:

@Repository
public interface PlayerStatisticsDataRepository extends JpaRepository<PlayerStatisticsData, Long> {

    @Query("SELECT new com.yourpackage.dto.PlayerStatsDto(ps.id, ps.playerName, " +
           "(SELECT pt FROM PlayerTransaction pt WHERE pt.playerStats = ps AND pt.timestamp > :cutoffTime)) " +
           "FROM PlayerStatisticsData ps")
    List<PlayerStatsDto> findWithRecentTransactions(@Param("cutoffTime") LocalDateTime cutoffTime);
}

这种方式直接查询出过滤后的结果,避免加载所有冗余的Transaction数据。

2. Hibernate过滤器

在PlayerTransaction实体上定义过滤器规则:

@Entity
@FilterDef(name = "filterRecentTransactions", parameters = @ParamDef(name = "cutoffTime", type = LocalDateTime.class))
@Filter(name = "filterRecentTransactions", condition = "timestamp > :cutoffTime")
public class PlayerTransaction {
    @Id
    private Long id;
    private LocalDateTime timestamp;
    @ManyToOne
    private PlayerStatisticsData playerStats;
    // 其他字段和方法
}

查询时启用过滤器:

// 从EntityManager获取Hibernate Session
Session session = entityManager.unwrap(Session.class);
// 启用过滤器并设置时间参数
session.enableFilter("filterRecentTransactions")
       .setParameter("cutoffTime", LocalDateTime.now().minusDays(7)); // 示例:近7天的数据

// 此时查询出来的PlayerStatisticsData,其transactions列表只会包含符合条件的记录
List<PlayerStatisticsData> statsList = session.createQuery("FROM PlayerStatisticsData", PlayerStatisticsData.class).list();

二、MongoDB(Spring Data MongoDB场景)

如果是MongoDB文档库,嵌套数组的过滤更加灵活,推荐用聚合管道或者投影查询:

1. 聚合管道过滤

// 构建聚合管道
Aggregation aggregation = Aggregation.newAggregation(
    // 可选:先匹配目标PlayerStatisticsData(比如按ID筛选)
    Aggregation.match(Criteria.where("_id").is(playerStatsId)),
    // 投影时过滤transactions数组
    Aggregation.project()
        .andInclude("playerName", "level") // 保留你需要的其他根字段
        .and(Aggregation.filter("transactions", "this.timestamp > :cutoffTime"))
        .as("transactions")
);

// 执行聚合查询
AggregationResults<PlayerStatisticsData> results = mongoTemplate.aggregate(
    aggregation,
    "playerStatisticsData", // 集合名
    PlayerStatisticsData.class
);
PlayerStatisticsData filteredStats = results.getUniqueMappedResult();

2. 直接用Query投影

Query query = new Query();
// 可选:添加根文档的筛选条件
query.addCriteria(Criteria.where("_id").is(playerStatsId));
// 过滤transactions数组
query.fields().project("transactions", Aggregation.filter("transactions", "this.timestamp > ?0", cutoffTime));

PlayerStatisticsData filteredStats = mongoTemplate.findOne(query, PlayerStatisticsData.class);

三、关键注意事项

  • 索引优化:不管用哪种数据库,都要给PlayerTransaction的timestamp字段建立索引,大幅提升过滤查询的速度
  • 批量查询性能:JPA场景下批量查询时,避免N+1问题,优先用构造函数投影的方式;MongoDB场景下聚合管道要注意避免不必要的阶段

内容的提问来源于stack exchange,提问作者Batimonster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:01:43