Actualmente, tengo problemas con el funcionamiento del sistema de documentos MongoDB. Quiero obtener elementos de la matriz con una identificación generada automáticamente, pero no sé cómo obtener esos datos específicos.
mi esquema actual es
const ItemPricesSchema = new mongoose.Schema({ _id : { type: String }, ItemsPrices: { type: [{ barcode : { type: String }, itemName : { type: String }, price : { type: String } }] } });los datos actuales se almacenan de esta manera
{ "_id": "sha@cc", "ItemsPrices": [ { "barcode": "345345", "itemName": "maggie", "price": "45", "_id": "620a971e11120abbde5f4c3a" }, { "barcode": "356345", "itemName": "monster", "price": "70", "_id": "620a971e11120abbde5f4c3b" } ], "__v": 0 }lo que quiero lograr es que quiero encontrar elementos de matriz a través de identificadores
si quiero un elemento de matriz específico con id "620a971e11120abbde5f4c3b", ¿qué debo hacer? He probado $unwind , $in, $match...
el resultado debería ser como
{ "_id": "sha@cc", "ItemsPrices": [ { "barcode": "356345", "itemName": "monster", "price": "70", "_id": "620a971e11120abbde5f4c3b" } ], "__v": 0 }lo que probé es así de la respuesta
router.get('/filter/:id', async (req, res) => { try { const item = await ItemPricesSchema.aggregate([ {$project: { "ItemsPrices": { $filter: { input: "$ItemsPrices", as: "item", cond: { $eq: [ "$$item._id", "620a8dd1c88ae3eb88a8107a" ] } } } } } ]) res.json(item); console.log(item); } catch (error) { res.status(500).json({message: error.message}); } })y devuelve algo como esto (matrices vacías)
[ { "_id": "xvz@zyx.z", "ItemsPrices": [] }, { "_id": "zxc@xc.czx", "ItemsPrices: [] }, { "_id": "asd@asd.asd", "ItemsPrices": [] }, { "_id": "qwe@qwe.qwe", "ItemsPrices": [] } ]pero si busco precio $$item.price
cond: { $eq: [ "$$item.price", "30" ] }devuelve la salida perfecta
[ { "_id": "xvz@zyx.z", "ItemsPrices": [] }, { "_id": "zxc@xc.czx", "ItemsPrices: [] }, { "_id": "asd@asd.asd", "ItemsPrices": [] }, { "_id": "qwe@qwe.qwe", "ItemsPrices": [ { "barcode":"234456345", "price":"30", "itemName":"monster", "_id":"620a8dd1c88ae3eb88a8107a" } ] } ]Puede hacer una agregación con $project y aplicar $filter en la parte de la matriz. En mongoose puede aplicar la consulta de agregación de una manera más o menos similar https://mongoosejs.com/docs/api/aggregate.html
db.collection.aggregate([ { $project: { "ItemsPrices": { $filter: { input: "$ItemsPrices", as: "item", cond: { $eq: [ "$$item._id", mongoose.Types.ObjectId("620a971e11120abbde5f4c3b") ] } } }, "__v": 1 //when projecting 1 means in the final result this field appears } } ])Opción 1:
Use $filter en una consulta de agregación como lo explica cmgchess
Opcion 2:
Si solo desea un objeto de la matriz, puede usar $ elemMatch así:
db.collection.find({ "ItemsPrices._id": "620a971e11120abbde5f4c3b" }, { "ItemsPrices": { "$elemMatch": { "_id": "620a971e11120abbde5f4c3b" } } })Ejemplo aquí
Pero tenga cuidado, al usar $elemMatch solo se devuelve el primer elemento. Verifique este otro ejemplo donde hay dos objetos con el _id deseado pero solo devuelve uno.
Como se dijo antes, si solo tiene uno (o solo existe uno), tal vez pueda usar find y $elemMatch para evitar un filtro por toda la matriz. Pero si pueden ser múltiples valores, use $filter .