$ exist will not use an index, but you can change your data structure to
photos: [ {id:123, url: '...', title: '...', ... }, {id:456, url: '...', title: '...', ... }, ... ]
and then use
db.users.ensureIndex({photos.id:1})
to create an index for the photo id.
I seem to be mistaken, in fact you can force your $ exist query to use your index. Let's continue to use the above structure, but your photo identifier is not necessarily contained, that is, some documents will have an "id" key, and some will not. Then you can create a sparse index on it:
db.users.ensureIndex({'photos.id': 1}, {'sparse': true})
then run the query as follows:
db.users.find({'photos.id': {$exists: true}}).hint({'photos.id': 1})
you can add an explanation to see if the query uses an index. Here is my result, my mobile key for mobile devices is similar to your photos.id:
> db.test.count() 50000 > db.test.find({'mobile': {$exists: true}}).hint({'mobile': 1}).explain() { "cursor" : "BtreeCursor mobile_1", "nscanned" : 49999, "nscannedObjects" : 49999, "n" : 49999, "millis" : 138, "nYields" : 0, "nChunkSkips" : 0, "isMultiKey" : false, "indexOnly" : false, "indexBounds" : { "mobile" : [ [ { "$minElement" : 1 }, { "$maxElement" : 1 } ] ] } } > db.test.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.test", "name" : "_id_" }, { "v" : 1, "key" : { "mobile" : 1 }, "ns" : "test.test", "name" : "mobile_1", "sparse" : true, "background" : true } ]
Hope to help!