Tengo una colección MongoDB en forma de:
users: { { user_id: 1000, activities: [ {id: 1, activity: 'swimming'}, {id: 2, activity: 'running'}, {id: 3, activity: 'biking'},... ] },... } y quiero obtener el documento de actividad que coincida con una identificación específica. Por ejemplo, si consulto usando {id: 1} , quiero una salida de {id: 1, activity: 'swimming'} . Actualmente, estoy tratando de usar findOne({activities: {$elemMatch: {id: 1}}}) , pero devuelve el documento de usuario completo (la identificación del usuario y todas las actividades).
El código que estoy usando es:
id = req.body.queryID; db.collection('users').findOne({activities: {$elemMatch: {id}}}) .then((document) => { console.log(document); // more code after this }); También intenté consultar usando added aggregate() y findOne({}, {activities: {$elemMatch: {id}}}) , pero no pude resolverlo.
Estoy en MongoDB versión 4.4.8 según db.version() . ¡Cualquier ayuda es apreciada!
Puede usar el método aggregate con las canalizaciones de unwind , match y project
db.users.aggregate([ {$unwind: "$activities"}, {$match: {"activities.id": id}}, {$project: {id: "$activities.id", activity: "$activities.activity", _id: 0}} ])NOTA: Este código está escrito usando la sintaxis de mongo shell.
La consulta hace lo siguiente
unwind que primero extrae todos los elementos de la matriz de actividades.match encuentra el elemento de matriz que tiene la identificación que estamos buscandoproject devuelve el resultado deseadoEspero que esto ayude
Tus intentos se ven cercanos, creo que solo necesitas juntarlos. findOne toma dos argumentos opcionales, una consulta y una proyección. La consulta le dice a MongoDB qué documento buscar y devolver. El documento de proyección le dice a MongoDB qué campo(s) incluir en el documento devuelto por la consulta.
Lo que tienes aquí:
db.collection('users').findOne({ activities: { $elemMatch: { id }}}) Pasa un argumento, la consulta. Buscará un documento donde haya un elemento en la matriz de activities con una id igual al valor de la variable id . También podría escribir esto como:
db.collection('users').findOne({ "activities.id": id }) También le gustaría devolver solo documentos en la matriz de activities con una identificación coincidente. Aquí es cuando haría algo como su otro intento, donde $elemMatch está en el segundo argumento, la proyección:
db.collection('users').findOne({}, {activities: {$elemMatch: {id}}})Pero debido a que pasó una consulta vacía, MongoDB devolverá cualquier documento, no necesariamente uno que contenga una actividad con una ID coincidente.
Entonces, si pasa tanto una consulta como la proyección, creo que debería obtener lo que está buscando. Podría verse así:
db.collection('users').findOne({ "activities.id": id }, { activities: { $elemMatch: { id }}}) Esto incluirá solo el campo _id y el documento de activities correspondiente, si existe. Si desea incluir otros campos del documento, deben incluirse explícitamente. Consulte esta documentación sobre proyección .
Por favor intente de la siguiente manera:
db.users.aggregate([ { '$unwind': '$activities' }, { '$match': { 'id': id } }, { '$project': { 'activity': '$activities.activity', 'id': '$activities.id', '_id':0 } } ]);