Actualmente estoy trabajando en una pequeña aplicación de ruleta de chat. Para eso utilizo MongoDB y NodeJS en el Backend. Para enumerar todos los canales de chat, quiero unir dos colecciones. Los elementos del primero (chats) tienen matrices anidadas:

{
  title: 'example 1',
  country: 'UK',
  ...
  chat: [
    {
      details: 'chat1 infos',
      channel: [
        '5ea3257d4b861a5aa0d03111',
        '5ea3257d4b861a5aa0d03122'
      ]
    },
    {
      details: 'chat2 infos',
      channel: [
        '5ea3257d4b861a5aa0d03333'
      ]
    }
  ]
}

El segundo (canales) almacena todos los detalles:

{
  _id: '5ea3257d4b861a5aa0d03111',
  title: 'Channel1',
  details: 'Channel1 Details'
},
{
  _id: '5ea3257d4b861a5aa0d03222',
  title: 'Channel2',
  details: 'Channel2 Details'
},
{
  _id: '5ea3257d4b861a5aa0d03333',
  title: 'Channel3',
  details: 'Channel13 Details'
}

El resultado debería verse así:

{
  title: 'example 1',
  country: 'UK',
  ...
  chat: [
    {
      details: 'chat1 infos',
      channel: [
        {
          _id: '5ea3257d4b861a5aa0d03111',
          title: 'Channel1',
          details: 'Channel1 Details'
        },
        {
          _id: '5ea3257d4b861a5aa0d03222',
          title: 'Channel2',
          details: 'Channel2 Details'
        }
      ]
    },
    {
      details: 'chat2 infos',
      channel: [
        {
          _id: '5ea3257d4b861a5aa0d03333',
          title: 'Channel3',
          details: 'Channel13 Details'
        }
      ]
    }
  ]
}

Lo intenté usando $ lookup:

db.collection('chats').aggregate([
  { "$lookup": {
    "from": "channel",
    "localField": "chat.channel",
    "foreignField": "_id",
    "as": "chat.channel"
  } }
]);

Pero con eso, me uno a todos los resultados en cada canal. Independientemente de qué identificadores estén contenidos en el canal. ¿Cómo puedo unirme a las colecciones para obtener el resultado descrito?

0
Nico Schuck 25 abr. 2020 a las 22:23

2 respuestas

La mejor respuesta

Probar esto

db.chats.aggregate([
  {
    $unwind: "$chat" // we need this as we have an array of chats, and each chat element has an array of channels
  },
  {
    $lookup: {
      from: "channels", // will use pipeline in lookup to get rid of multiple group stages
      let: {
        channelIds: "$chat.channel"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $in: [
                "$_id", // _id of channel
                "$$channelIds" // channel ids from chat.channel array
              ]
            }
          }
        }
      ],
      as: "chat.channel"
    }
  },
  {
    $group: {
      _id: "$_id", // group the unwinded chat array
      title: {
        $first: "$title"
      },
      country: {
        $first: "$country"
      },
      chat: {
        $push: "$chat"
      }
    }
  }
])

Compruebe esto Mongo Playground

0
Mohammed Yousry 25 abr. 2020 a las 21:13

Puedes seguir esta sección

puedes usar populate

 let _doc =await firstModel.find().populate("channels")

0
Shuvro 25 abr. 2020 a las 20:27