2011-11-18 15 views
7

Si tengo los datos en mi colección users que se parece a:

{ name: '...', 
    email: '...', 
    ..., 
    photos: { 
    123: { url: '...', title: '...', ... }, 
    456: { url: '...', title: '...', ... }, 
    ... 
    } 
} 

Y quiero encontrar el usuario propietario del carnet de identidad 127, entonces yo estoy usando la consulta:

db.users.find({'photos.127': {'$exists' => true} }); 

tengo intentado, pero no parece posible hacer que MongoDB use un índice para esta consulta. El índice que probé fue: db.users.ensureIndex({photos:1});. Y cuando usé explain() mongo me dijo que estaba usando un BasicCursor (es decir, no se utilizó ningún índice).

¿Es posible crear un índice que mongo usará para esta consulta?

Respuesta

12

No, no hay forma de decirle a mongodb que use index para la consulta existente. La indexación está completamente relacionada con los datos. Como $ existe solo está relacionado con las claves (campos) no se puede usar en los índices.

$ exists simplemente verifica si la clave (o campo) dada existe en el documento.

+0

Genial, gracias por la confirmación. – bantic

+8

¡NO! Probé con mongodb 2.4.3 y UTILIZA el índice. Tenga en cuenta que los campos inexistentes tienen valor nulo en el índice. –

+2

MongoDB 3.0.3: 'explain' para ambos' find ({field: {$ exists: 1}}) 'y' find ({field: {$ ne: null}}) 'parece que va a usar index, pero mientras que la segunda consulta finaliza de manera instantánea, la primera prueba (con exploración completa, supongo). – vorou

6

$ existen no va a usar el índice, pero se puede cambiar la estructura de datos para

photos: [ 
    {id:123, url: '...', title: '...', ... }, 
    {id:456, url: '...', title: '...', ... }, 
    ... 
    ] 

y luego usar

db.users.ensureIndex({photos.id:1}) 

para crear un índice para el carnet de identidad.

Parece que estoy equivocado, de hecho, puede forzar su consulta $ exists para usar su índice. Vamos a seguir usando la estructura anterior, pero su identificación con foto no está ciertamente contenida, es decir algunos documentos tendrán la clave 'id' y otros no. A continuación, puede crear índice disperso en él:

db.users.ensureIndex({'photos.id': 1}, {'sparse': true}) 

entonces consulta como esta:

db.users.find({'photos.id': {$exists: true}}).hint({'photos.id': 1}) 

puede agregar a explicar para ver si la consulta está utilizando índice. Aquí está mi resultado, la llave móvil de mi colección es similar a su 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 
     } 
] 

Esperanza para ayudar!

Cuestiones relacionadas