67

suppose I have the following datastructure:

var user = {_id: 'foo', age: 35};
var post = {_id: '...', author: {$ref: user, $id: 'foo'},...};

How can I query all posts which references user[foo]? I tried the following but not work:

db.post.find('author._id': 'foo');
var u = db.user.find({_id: 'foo'});
db.post.find('author': u);

neither can I find the answer from the official document and google!

Anyone has any idea?

Andrew Orsich
  • 52,935
  • 16
  • 139
  • 134
Gelin Luo
  • 14,035
  • 27
  • 86
  • 139
  • 2
    One thing to keep in mind from the MongoDB API documentation: "Unless you have a compelling reason to use DBRefs, use manual references instead" – IcedDante Aug 02 '14 at 23:21
  • 2
    @lcedDante, that's true. I start to use manual references across my projects years agao and never come back to dbref. had to say it's much easier to manage. – Gelin Luo Aug 04 '14 at 00:26
  • db.post.find('author.$id': 'foo') has missing {} in query , and $ before _id. this would be: db.post.find({'author.$id': 'foo'}) – Girish Gupta Oct 19 '16 at 04:26

6 Answers6

105

Got it:

db.post.find({'author.$id': 'foo'})
Gelin Luo
  • 14,035
  • 27
  • 86
  • 139
  • 3
    Does anyone idea how to accomplish the same using MongoEngine? – Justin Watt Oct 29 '12 at 20:22
  • 3
    This is the best I've been able to come up with: `Post.objects(__raw__={'author.$id':'foo'})` – Justin Watt Oct 29 '12 at 20:45
  • 2
    I had to use db.post.find({'author.$id': ObjectId('foo')}) to get this to work. – JamieL Apr 18 '13 at 12:47
  • 3
    Yes usually it is `ObjectId('....')`, it could also be `NumberLong(...)`, and could also be `'foo'`, it really depends on which type you are using for the id column – Gelin Luo Apr 18 '13 at 22:16
  • 1
    Somebody with this issue with morphia? We have a workaround here but it is not so nice. – Joqus Aug 20 '13 at 17:02
  • 1
    @Joqus in Morphia I've tested this method: Author authorQuery = dataSource.find(Author.class, "name", "author-name").get(); List discs = dataSource.find(Disc.class).disableValidation().field("author.$id").equal(authorQuery.getId()).asList(); where Disc contains a reference to Author though a DBRef –  Jul 31 '16 at 13:25
18

This db.post.find('author.$id': 'foo') has missing the {}, so the correct sentence is:

db.post.find({'author.$id': 'foo'})

Also this can be achieved with:

db.post.find({'author': DBRef("user", ObjectId('foo'))})

But is more compact and practical the first way.

Mariano Ruiz
  • 4,314
  • 2
  • 38
  • 34
11

You can use the .$id reference but it will ignore any indexes on those fields. I would suggest ignoring that method unless you are querying it directly via the terminal or want to look up something quickly. In using large collections you will want to index the field and query it using the below method.

If you want to use an index query using the following:

db.post.find('author' : { "$ref" : 'user', "$id" : 'foo' , "$db" :'database_name' })

If foo is an object id

db.post.find('author' : { "$ref" : 'user', "$id" : ObjectId('foo') , "$db" :'database_name' })

You can create an index on author by

db.post.ensureIndex( {'author' : 1 } );
RedPhoenix
  • 306
  • 2
  • 3
3

For anyone looking for a Java solution to this then if you are using mongojack its really easy:

collection.find(DBQuery.is("user", new DBRef(user.getId(), User.class)));

Where collection is a JacksonDBCollection.

dannrob
  • 1,061
  • 9
  • 10
1

In mongoengine you should just use the instance of the referenced object. It should have the ID set. Suppose the author is the Author document instance. So using this:

Post.objects(author__eq=author)

you can go through all posts of this author. Post.author should be defined as ReferenceField

Kostanos
  • 9,615
  • 4
  • 51
  • 65
-1

Using Mongo 2.4.1 version

This is how you do it on command line for OLA collection where @DBRef dbrefName

db.OLA.find({"dbrefName.someFieldValue" : "Personal"});

Exact query

db.OLA.find({"dbrefName.$id" : ObjectId("1234")});

java_dude
  • 4,038
  • 9
  • 36
  • 61