0

I have the following document:

[
  {
    "_id": "a",
    "elements": [
      {
        "mode": "ALWAYS",
        "type": "RED",
        "number": "123"
      },
      {
        "mode": "ALWAYS",
        "type": "BLUE",
        "number": "99123124"
      }
    ]
  },
  {
    "_id": "b",
    "elements": [
      {
        "mode": "ALWAYS",
        "type": "RED",
        "number": "123"
      },
      {
        "mode": "ALWAYS",
        "type": "BLUE",
        "number": "123123123"
      }
    ]
  }
]

And I need to duplicate for single entry only the element of type "BLUE" but changing its type to GREEN. How can I accomplish that? I tried without luck using a db.col.push but I couldn't duplicate the specific entry "BLUE" of the array "elements".

This is the expected goal:

[
    {
      "_id": "a",
      "elements": [
        {
          "mode": "ALWAYS",
          "type": "RED",
          "number": "123"
        },
        {
          "mode": "ALWAYS",
          "type": "BLUE",
          "number": "99123124"
        },
        {
          "mode": "ALWAYS",
          "type": "GREEN",
          "number": "99123124"
        }
      ]
    },
    {
      "_id": "b",
      "elements": [
        {
          "mode": "ALWAYS",
          "type": "RED",
          "number": "123"
        },
        {
          "mode": "ALWAYS",
          "type": "BLUE",
          "number": "123123123"
        },
        {
            "mode": "ALWAYS",
            "type": "GREEN",
            "number": "123123123"
        }
      ]
    }
  ]
1
  • 1
    I don't think this can be accomplished server-side in a single update statement. I believe you will have to use an application to orchestrate at least two commands: One to find records eligible for update, another for creating update operations based on retrieved data. If taking this approach I highly recommend using bulkWrites to speed up the process assuming large datasets. Commented Dec 8, 2021 at 17:59

1 Answer 1

1

Query

  • pipeline update requires MongoDB >= 4.2
  • map and convert the blues to greens
  • filter to remove those that weren't blues
  • add those greens to the initial elements array

Test code here

update(
{},
[{"$set": 
   {"elements": 
     {"$concatArrays": 
       ["$elements",
        {"$filter": 
          {"input": 
            {"$map": 
              {"input": "$elements",
               "in": 
               {"$cond": 
                 [{"$eq": ["$$this.type", "BLUE"]},
                  {"$mergeObjects": ["$$this", {"type": "GREEN"}]}, null]}}},
            "cond": {"$ne": ["$$this", null]}}}]}}}])
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, let me test it. It seems to be working
i changed the query to work even if you have many blues, previous worked for 1 max 1 blue per elements

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.