1
 db.collectionB.findOne()
 {
    "_id" : NumberLong(24),
    "class" : "Top",
    "type" : DBRef("collectionA", NumberLong(47))
 }
db.collectionA.findOne()
{
   "_id" : NumberLong(47),
   "name" : "John",
   "position" : 2 
}

QUERY to be formed : db.collectionB.find({type: DBRef("collectionA", NumberLong(47))});

There are a number of documents in collection A & collectionB. I want to search the documents where "type" in collectionB is referring to document where "_id" is NumberLong(47) in collectionA.

BasicDBObject query =   new BasicDBObject("name","John");
DBObject db_object = findOne("collectionA",query);
DBRef myDbRef = new DBRef(db,"collectionB",db_object); 
DBObject doc = myDbRef.fetch(); 
System.out.println(doc);

It gives the output null. Why?

Parvin Gasimzade
  • 25,180
  • 8
  • 56
  • 83
SET
  • 55
  • 1
  • 5

1 Answers1

4

The 3-argument constructor of DBRef takes the following arguments:

  • Database
  • Namespace
  • ID

Your second argument isn't a namespace, it is just the collection. It should be a string "yourDatabaseName.collectionB".

Your third argument isn't just an ID, it's a complete object. That way the DBRef points to a document where the value of the field _id is a complete copy of the document you pass. Such a document doesn't exist, so fetching the DBRef returns null.

To create a valid DBRef you only pass the value of _id to the constructor of DBRef.

But when I understood your requirement "I want to search the documents where "type" in collectionB is referring to document where "_id" is NumberLong(47) in collectionA." correctly, you don't even have to query collectionA. DBRef's are just transparent sub-objects with this structure: { "$ref" : <value>, "$id" : <value>, "$db" : <value> }. So you should be able to find the desired documents with:

db.collectionB.find("type.$id": 47);

This assumes that all the dbref's under type reference the same collection and database. When that's not the case, you need to include these in your query to avoid results referencing another collection:

db.collectionB.find("type.$id": 47, "type.$ref": "collectionA", "type.$db": <database name>);
Philipp
  • 67,764
  • 9
  • 118
  • 153
  • Thanks for the info. It was really helpful. One more confusion, while passing arguments to DBRef constructor, which collection is used-the collection which is referring (collectionB) or the collection being referenced (collectionA) – SET Oct 11 '13 at 12:20
  • DBRef myDbRef = new DBRef(db,"mydbname.collectionA",db_object.get("_id")); Is this ok? – SET Oct 11 '13 at 12:21
  • @SET the namespace you pass to the DBRef constructor is of course the one the DBRef should point to. – Philipp Oct 11 '13 at 13:00