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?
The 3-argument constructor of DBRef takes the following arguments:
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>);