PDA

View Full Version : MongoDB repository queries for documents with DBRef attributes



sskrobotov
Jul 12th, 2011, 07:13 AM
Hi Team,

Could you please give me a hint about using queries for documents with DBRef attributes? To be more specific, I have following classes:



@Document
public class Type {

@Id
private ObjectId id;
}

@Document
public class Entity {

@Id
private ObjectId id;

@DBRef
private Type type;


public Entity(Type type) {
this.type = type;
}
}

public interface TypeRepository extends MongoRepository<Type, String> {
}

public interface EntityRepository extends MongoRepository<Entity, String> {
List<Entity> findByType(Type p);
}


So, here I'm creating an instance of Entity and then trying to find it by given type. However, as soon as type attribute is stored in mongodb as a DBRef object, query fails.



public class Main {

public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("META-INF/beans.xml");
MongoTemplate mongoTemplate = context.getBean(MongoTemplate.class);
RepositoryFactorySupport repoFactory = new MongoRepositoryFactoryBean.MongoRepositoryFactory( mongoTemplate);

EntityRepository entityRepository = repoFactory.getRepository(EntityRepository.class);
TypeRepository typeRepository = repoFactory.getRepository(TypeRepository.class);

entityRepository.deleteAll();
typeRepository.deleteAll();

Type t = new Type();
typeRepository.save(t);

Entity e = new Entity(t);
entityRepository.save(e);

System.out.println(entityRepository.findAll());
System.out.println(entityRepository.findByType(t)) ;
}
}


As a result, call to findAll returns a single object (as expected), and call to findByType returns an empty collection.

Am I doing anything wrong here?

The best solution that I've found is to use custom query as follows:


public interface EntityRepository extends MongoRepository<Entity, String> {

@Query("{ 'type': {'$ref': 'type', '$id': { '$oid': ?0 } } }")
List<Entity> findByType(String typeIdAsString);
}


I guess it would be a nice improvement if query creator service would inspect if query criteria param is a DBRef in a document class and therefore should also be converted to DBRef object before putting to query.

Thanks

rakesh_sinha
Jun 14th, 2013, 04:32 AM
I tried but it works only for "id" field. How should my query look like if i want to query for another field. I have an object:
Freelancer {
@Id
String id;
@DBRef
List<Project> projects;
}

Project {
@Id
String id;
String name;
String title;
}

If i want to search based on title, i assume the query should look like:
@Query("{ 'projects': {'$ref': 'project', '$title': { '$title' : ?0 } } }")

This doesn't work.

Hi Team,

Could you please give me a hint about using queries for documents with DBRef attributes? To be more specific, I have following classes:



@Document
public class Type {

@Id
private ObjectId id;
}

@Document
public class Entity {

@Id
private ObjectId id;

@DBRef
private Type type;


public Entity(Type type) {
this.type = type;
}
}

public interface TypeRepository extends MongoRepository<Type, String> {
}

public interface EntityRepository extends MongoRepository<Entity, String> {
List<Entity> findByType(Type p);
}


So, here I'm creating an instance of Entity and then trying to find it by given type. However, as soon as type attribute is stored in mongodb as a DBRef object, query fails.



public class Main {

public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("META-INF/beans.xml");
MongoTemplate mongoTemplate = context.getBean(MongoTemplate.class);
RepositoryFactorySupport repoFactory = new MongoRepositoryFactoryBean.MongoRepositoryFactory( mongoTemplate);

EntityRepository entityRepository = repoFactory.getRepository(EntityRepository.class);
TypeRepository typeRepository = repoFactory.getRepository(TypeRepository.class);

entityRepository.deleteAll();
typeRepository.deleteAll();

Type t = new Type();
typeRepository.save(t);

Entity e = new Entity(t);
entityRepository.save(e);

System.out.println(entityRepository.findAll());
System.out.println(entityRepository.findByType(t)) ;
}
}


As a result, call to findAll returns a single object (as expected), and call to findByType returns an empty collection.

Am I doing anything wrong here?

The best solution that I've found is to use custom query as follows:


public interface EntityRepository extends MongoRepository<Entity, String> {

@Query("{ 'type': {'$ref': 'type', '$id': { '$oid': ?0 } } }")
List<Entity> findByType(String typeIdAsString);
}


I guess it would be a nice improvement if query creator service would inspect if query criteria param is a DBRef in a document class and therefore should also be converted to DBRef object before putting to query.

Thanks

Andrei Tsibets
Jun 17th, 2013, 12:23 AM
You have to do two queries:
http://forum.springsource.org/showthread.php?137956-Query-on-DBREF-document-Fileds