query objects elemmatch array arrays mongodb

arrays - objects - Obtenga un elemento particular de mongoDB array



mongodb subdocument query (4)

Esta pregunta ya tiene una respuesta aquí:

Tengo la colección mongo como a continuación

{ "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 obtener la única fecha del libro b1 y el autor xyz.

Tengo una consulta como a continuación

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

pero da salida de la siguiente manera

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

Quiero obtener la única fecha del libro b1 y otra xyz. Significa solo "books" : {"date" : 2-4-00}

¿Es posible en mongo o estoy haciendo algo mal?


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

Puede hacer esto con agregado o reducción de mapa. 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'' } } ]);

Obtendrás una matriz con una sola entrada como esta:

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

De lo contrario, si mongo 2.6+ puedes hacerlo de la manera más fácil:

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'' } ] }


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

No hay soporte para devolver solo sub documentos.

Este problema tiene un boleto sobresaliente en el rastreador de boletos de MongoDB.

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

Vea here un ejemplo de cómo usar esto.


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}})


si desea seleccionar solo el elemento coincidente, puede realizar consultas de esta manera.

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