如何在Spring Data MongoDB仓库的查询方法中使用投影类型?

10

我一直在使用Spring Data和MongoDB,并对于限制某些查询的数据量有疑问。我已经看到可以在MongoRepository中添加自定义查询,但是我没有看到任何关于限制数据量并返回基本上是大类子集的类的示例。

例如,我有一个User类,其中包含几个字段,但我还想创建一个UserShort类,其中只包含User类中的字段子集。例如,UserShort只包含idfirstName/lastName/email字段,而不包括其他所有字段。

我已经看到可以指定/限制返回的字段,但我能否将它们返回到另一个类中呢?目前,除非我指定User类,否则UserShort将返回null,但字段将限制为我指定的字段。不确定是否可能实现这一点?我意识到下面的User类并不是很庞大,但这是我想表达的概念。

一个用户界面:

public interface Users {}

子集类:

public class UserShort implements Users {

    @Id
    private String id;

    private String firstName;
    private String lastName;

    @Indexed(unique = true)
    private String email;

    //getters / setters
}

完整的类:

@Document
public class User implements Users {

    @Id
    private String id;

    private String firstName;
    private String lastName;
    private String username;
    private String password;
    private Date dob;
    private Status status;

    @Indexed(unique = true)
    private String email;

    private Gender gender;
    private String locale;
    private Date registerDate;

    @DBRef
    private List<UserAddress> addresses;

    public User(){
        addresses = new ArrayList<UserAddress>();
    }

    //getters / setters
}

并且还有存储库接口:

public interface UserRepository extends MongoRepository<Users, String> {

    public User findByEmail(String email);

    @Query(value="{ 'email' : ?0 }", fields="{ 'firstName' : 1, 'lastName' : 1}")
    public UserShort findUserShortByEmail(String email);

}
1个回答

9
只要查询方法的返回类型可以赋值给托管域类型(在您的情况下为Users),我们将优先使用返回类型来确定要运行查询的集合。因此,在您的情况下,我们将针对userShort而不是users执行查询,这就是为什么您没有得到任何结果的原因。这种行为的目的是支持将继承层次结构存储到不同的集合中。
如果您将库的域类型切换为User,则一切都应该按预期工作。这也有利于防止客户端向save(…)方法提交UserShort实例,后者会清除User中但UserShort中不存在的属性。以下是最终的存储库接口声明。
interface UserRepository extends MongoRepository<User, String> {

    User findByEmail(String email);

    @Query(value="{ 'email' : ?0 }", fields="{ 'firstName' : 1, 'lastName' : 1}")
    UserShort findUserShortByEmail(String email);
}

P.S.: 在评论中,@byte-crunch 指出目前此功能仅适用于投影的集合,而不适用于返回单个实例。这已经被报告并在 DATAMONGO-1030 中得到修复,将在 1.5.4 和 1.6.0 GA 版本中提供。


谢谢您的回复!您发布的内容实际上是我在引入用户界面之前所拥有的,我认为如果它们共享一个公共接口,我可能能够返回User和UserShort。但是这就带来了您解释的受管理域类型的问题。如果我尝试保存(..)UserShort,那么我将从“Users”集合中删除User的字段(不好)。但是,如果将“User”指定为托管类型,并且UserShort是findUserShortByEmail()的返回类型,则仍然会得到空结果。如果我指定User,则可以正常工作。 - byte-crunch
我想再添加一个有趣的方面... 如果我使用你上面指定的内容,只是做了一个修改 - byte-crunch
抱歉,之前发布了不完整的内容。如果我将其作为列表,即:List<UserShort> findUserShortByEmail(String email); 那么它可以正常工作。我的 UserShort 在列表中得到了正确的填充。但是如果没有列表,则结果为空。 - byte-crunch
这确实是一个 bug。我已经提交了 DATAMONGO-1030 - Oliver Drotbohm
感谢您的支持和协助,Oliver。 - byte-crunch
这个问题已经解决了。我已经相应地更新了我的答案。 - Oliver Drotbohm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接