Reputation: 279
I have been playing around with Spring Data and MongoDB and have a question about limiting the amount of data for certain queries. I've seen adding custom queries within the MongoRepository
, however I haven't seen any examples of limiting the amount of data and returning classes that are basically a subset of larger classes.
For instance I have a User
class that has several fields, but I also want to create a UserShort
class that has a subset of the fields in the User
class. For instance UserShort
would only contain the id
and firstName
/ lastName
/ email
fields, rather than everything.
I've seen I can specify/limit the fields that are returned, but can I have those returned into a different class? At the moment the UserShort
will return null
unless I specify the User
class instead, but the fields will be limited to the ones I specify. Wasn't sure if this is possible at all? I realize the User
class below isn't huge, but it's the concept I'm after.
A user interface:
public interface Users {}
Subset class:
public class UserShort implements Users {
@Id
private String id;
private String firstName;
private String lastName;
@Indexed(unique = true)
private String email;
//getters / setters
}
Full class:
@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
}
And the repository interface:
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);
}
Upvotes: 10
Views: 10356
Reputation: 83161
As long as the return type of the query method is assignable to the managed domain type (Users
in your case) we will prefer the return type to determine the collection to run the query against. Thus, in your case we'd execute the query against userShort
instead of users
which is why you do not get any results. That behavior is in place to support storing inheritance hierarchies into different collections.
If you switched to User
as the domain type for the repository, things should work exactly as expected. This would also have the benefit of preventing clients from handing UserShort
instances to the save(…)
method which will wipe out properties contained in User
but not in UserShort
. Here's the final repository interface declaration.
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 outlined in the comments that this currently only works for collections of projections but not for returning single instances. This has been reported and fixed in DATAMONGO-1030 and will be available in 1.5.4 and 1.6.0 GA.
Upvotes: 9