Tengo una colección de MongoDB con documentos de la siguiente estructura (se omiten partes no interesantes):
{ displayFieldId: "abcd", fields: [ { fieldId: "efgh", value: "cake" }, { fieldId: "abcd", value: "cheese" }, .... ], .... } Me gustaría ejecutar una consulta en esta colección para obtener solo el elemento en la matriz de fields cuyo fieldId de campo coincide con el ID de campo de displayFieldId del documento. El resultado de la consulta sobre el documento anterior debería ser:
{ fields: [ { fieldId: "abcd", value: "cheese" } ], .... } Construí la siguiente consulta. Hace lo que quiero, con la excepción de que displayFieldValue está codificado de forma rígida
db.containers.find({}, { fields: { $elemMatch: { fieldId: "abcd" } } }); ¿Hay alguna manera de hacer que mire el displayFieldId del documento y use ese valor en lugar del "abcd" codificado?
El servidor está ejecutando MongoDB 3.2.6
Si es posible, me gustaría hacer esto sin agregación, pero si eso no se puede hacer, entonces la agregación tendrá que funcionar.
Con marco de agregación:
db.containers.aggregate([ { "$redact": { "$cond": [ { "$anyElementTrue": [ { "$map": { "input": "$fields", "as": "el", "in": { "$eq": ["$$el.fieldId", "$displayFieldId"] } } } ] }, "$$KEEP", "$$PRUNE" ] } }, { "$project": { "displayFieldId": 1, "fields": { "$filter": { "input": "$fields", "as": "el", "cond": { "$eq": ["$$el.fieldId", "$displayFieldId"] } } }, "otherfields": 1, .... } } ])MongoDB 3.4 :
db.containers.aggregate([ { "$redact": { "$cond": [ { "$anyElementTrue": [ { "$map": { "input": "$fields", "as": "el", "in": { "$eq": ["$$el.fieldId", "$displayFieldId"] } } } ] }, "$$KEEP", "$$PRUNE" ] } }, { "$addFields": { "fields": { "$filter": { "input": "$fields", "as": "el", "cond": { "$eq": ["$$el.fieldId", "$displayFieldId"] } } } } } ]) Sin marco de agregación , usando $where (la consulta lenta):
db.containers.find({ "$where": function() { var self = this; return this.fields.filter(function(f){ return self.displayFieldId === f.fieldId; }).length > 0; } }).map(function(doc){ var obj = doc; obj.fields = obj.fields.filter(function(f){ return obj.displayFieldId === f.fieldId; }); return obj; })