node.jsmongodbmongodb-update

MongoDB - How to move an array from one array field to another


I have two fields in a MongoDB document publish and draft with schema as:

{
    publish: [[
                { type: String, required: true },
                { type: String, required: true }
            ]],
    draft: [[
                { type: String, required: true },
                { type: String, required: true }
            ]]
}

and value looks like this in DB:

{
    "draft": [
        [
          "Panic 2",
          "63d2648d373f7fea3fa9d387_1681628752497"
        ],
        //...
      ],
      "publish": [
        [
          "Ruins Exploration Gone Wrong!",
          "63d2648d373f7fea3fa9d387_1681628787816"
        ],
        [
          "Fresh Start",
          "63d2648d373f7fea3fa9d387_1681628805269"
        ],
        //...
      ]
}

Now I'm working on a query that can move the array

["Panic 2","63d2648d373f7fea3fa9d387_1681628752497"]

from draft to publish but I only have 63d2648d373f7fea3fa9d387_1681628752497 to achieve so.

How should I frame my query?

EDIT: I have tried some way and was able to pull the array from draft field but haven't been able to push that array to publish with only the presence of id.


Solution

  • Assume that the second element within the inner array is unique, you can perform the update with aggregation pipeline:

    1. $set

      selected - Filter the matching element for the id value from the draft array.

      draft - Filter the element to remove it (selected) from the draft array.

    2. $set

      published - Combine the selected array with published array.

      selected - Remove the selected field.

    db.collection.update({
      "draft": {
        $elemMatch: {
          $elemMatch: {
            $eq: "63d2648d373f7fea3fa9d387_1681628752497"
          }
        }
      }
    },
    [
      {
        $set: {
          selected: {
            $filter: {
              input: "$draft",
              cond: {
                $eq: [
                  {
                    $arrayElemAt: [
                      "$$this",
                      1
                    ]
                  },
                  "63d2648d373f7fea3fa9d387_1681628752497"
                ]
              }
            }
          },
          draft: {
            $filter: {
              input: "$draft",
              cond: {
                $ne: [
                  {
                    $arrayElemAt: [
                      "$$this",
                      1
                    ]
                  },
                  "63d2648d373f7fea3fa9d387_1681628752497"
                ]
              }
            }
          }
        }
      },
      {
        $set: {
          publish: {
            $concatArrays: [
              "$publish",
              "$selected"
            ]
          },
          selected: "$$REMOVE"
        }
      }
    ])
    

    Demo @ Mongo Playground