2011-04-06 10 views
26

tengo colección mongo, como a continuaciónelemento particular de MongoDB gama

{ 
    "auther" : "xyz" , 
    "location" : "zzz" , 
    "books" : 
    [ 
     {"book1" : "b1" , "date" : 2-3-00} , 
     {"book1" : "b2" , "date" : 4-9-00} 
    ] 
} 

{ 
    "auther" : "pqr", 
    "location" : "zzz" , 
    "books" : 
    [ 
     {"book1" : "b1" , "date" : 2-4-00} 
    ] 
} 

Quiero conseguir el único de la fecha de b1 libro y autor XYZ.

que tengo que consulta, como a continuación

db.coll.find({"auther" : "xyz" , "books.book1" : "b1"} , {"books.date" : 1}) 

pero es da salida de la siguiente manera

"books" : {"date" : 2-4-00} , "books" : {"date" : 4-9-00} 

Quiero conseguir el único de la fecha de b1 libro y otros .means xyz única "books" : {"date" : 2-4-00}

¿es posible en mongo o estoy haciendo algo mal?

Respuesta

22

El lenguaje de consulta MongoDB está diseñado para devolver todos los documentos coincidentes.

No se admite la devolución de sub documentos únicamente.

Este problema tiene un outstanding ticket en el registrador de tickets de MongoDB.


ACTUALIZACIÓN: parece que el billete se ha marcado como fijo.

Consulte here para ver un ejemplo de cómo usar esto.

+0

Esto se ha solucionado mientras tanto; eche un vistazo a http://stackoverflow.com/questions/3985214/mongodb-extract-only-the-selected-item-in-array –

+1

@DanDascalescu gracias por la actualización, he actualizado el original. –

+0

El segundo parámetro para buscar especifica qué campos recuperar, que efectivamente especifica qué sub-documentos necesita. – Leopd

5

Se puede hacer usando map/reduce, simplemente emite el elemento secundario en una colección temporal en línea. Es un Hack y funciona, sin embargo, desaconsejaría, ya que map/reduce tiene un solo subproceso y tiene una gran sobrecarga para lo que quieres lograr, es mucho más fácil extraer el subelemento en tu aplicación.

Algo como esto ...

mapa:

m = function() { 
    this.books.forEach(function(book){ 
     if(book1 == 'b1'){ 
      emit("books", {date: book.date,}); 
     } 
    }); 
} 

reducir:

r = function(key, values) { 
     return this; 
    } 

consulta:

 
    db.coll.mapReduce(m, r, {query : {"auther" : "xyz" , "books.book1" : "b1"}, out: { inline : 1}}) 

3

si desea seleccionar único elemento que emparejan puede consultar de esta manera.

b.coll.find ({ "auther": "xyz", "books.book1": "b1"}, { "libros de $ fecha..": 1})

1

Con un poco de imaginación (pre mongo v 2.6) ...

Puede hacer esto con agregado o mapa reducido. El agregado es más nuevo, más fácil y más optimizado. Aquí hay una muestra de devolución de un documento secundario con agregado suponiendo que su colección se denomina "Autores". Me tomé la libertad de deletrear las cosas correctamente.

Authors.aggregate([ 
    { $match: { author: 'xyz' } }, 
    { $unwind: '$books' }, 
    { 
    $project: { 
     _id: '$books.book1', 
     date: '$books.date' 
    } 
    }, 
    { $match: { '$_id' : 'b1' } } 
]); 

Volverás una matriz con una sola entrada, así:

[{ _id: 'b1', date: '2-4-00' }] 

De lo contrario, si mongo 2.6+ que puede hacer el camino más sencillo:

Authors.find({ 
    author: 'xyz', 
    books: { $elemMatch: { book1: 'b1' } } 
},'books') 

Donde obtendrá la colección de libros si se encuentra y solo un registro dentro de:

{ _id: 'xyz', books: [ { book1: 'b1', date: '2-4-00' } ] } 
Cuestiones relacionadas