4

I have following documents in my db

> db.person.find()
{ "_id" : ObjectId("1122"), "name" : "Alice", "age" : 20 }
{ "_id" : ObjectId("3344"), "name" : "Bob", "age" : 21 }
> db.article.find()
{ "_id" : ObjectId("aaaa"), "authors" : [ { "$ref" : "person", "$id" : "1122" } ] }
{ "_id" : ObjectId("bbbb"), "authors" : [   {
        "$ref" : "person",
        "$id" : "1122"
    },  {
        "$ref" : "person",
        "$id" : "3344"
    } ] }

and this is the code I've tried to find articles whose authors contain Bob

import pymongo
import bson.objectid

db = pymongo.MongoClient()['test']

bob_id = bson.objectid.ObjectId('3344')

article = db.article.find_one({ 'authors': { '$in': [ bob_id ] } })
print article
# None

article = db.article.find_one({ 'authors.$id': { '$in': [ bob_id ] } })
print article
# None

article = db.article.find_one({ 'authors.$id': { '$in': [ str(bob_id) ] } })
print article
# { article object }

It results in that the string representation should be passed instead of the ObjectId if I want to find any documents by DBRef, in pymongo.

Does mongo or pymongo do just a string matching for that (and thus losing efficiency)? Is there any more proper way to do reference queries?

neuront
  • 9,312
  • 5
  • 42
  • 71
  • 3
    You should use `bson.dbref.DBRef` objects to load/save this data. It looks like you've saved it as an embedded document with `$ref` and `$id` fields. And by the way: string matching is no less efficient then any other matching. – freakish Mar 15 '13 at 09:45
  • @freakish Thanks, I see. Is there any easy way to construct a `DBRef`, rather than `bson.dbref.DBRef('person', str(bob['_id']))`? – neuront Mar 15 '13 at 13:16
  • 1
    Don't pass stringified id to DBRef. Pass an ObjectId instance `DBRef('person', bob['_id'])`. Except for that I can't imagine easier way. :) – freakish Mar 15 '13 at 14:09

0 Answers0