6

I have collection which has an array field as follows.

availableProducts: [ "mobile", "laptop", "desktop"]

Now I would like to update this field to a string field at the same time i need to keep the values of array as comma separated strings as follows

availableProducts: "mobile,laptop,desktop"

Can we do this with almost 1 million records in MongoDB version 4.0

3 Answers 3

7

Much easier and understandable way:

db.collection.aggregate([
  {
    $addFields: {
      "availableProducts": {
        $reduce: {
          input: "$availableProducts",
          initialValue: "",
          in:{
            $concat:[
               "$$value",
               {
                  "$cond":{
                     "if":{
                        "$eq":[
                           "$$value",
                           ""
                        ]
                     },
                     "then":"",
                     "else":","
                  }
               },
               "$$this"
            ]
         }
        }
      }
    }
  },
  {$out:'collection'}
])

Source: https://docs.mongodb.com/manual/reference/operator/aggregation/reduce/

Sign up to request clarification or add additional context in comments.

Comments

2

You can do this from mongo shell, as follows:

Input documents:

{ "_id" : 1, "a" : [ "blue", "green", "red" ] }
{ "_id" : 2, "a" : [ "cat", "dog", "rat" ] }

The query:

db.arr1.find()
       .forEach( doc => { doc.a = doc.a.toString(); db.arr1.save(doc); } )

Result (the updated collection):

{ "_id" : 1, "a" : "blue,green,red" }
{ "_id" : 2, "a" : "cat,dog,rat" }

3 Comments

1 million records ... Sure you want to do a forEach (...save)?
@matthPen Why are you doubting? What is the issue? You can update 1 million documents in few minutes on a regular laptop.
My solution : nothing fetched from database, 1 request. Yours : 1 million documents from db, 1 million requests. And I don't speak of sharding or replication. Which one is the best?
0

You can achieve this with the following aggregation :

db.collection.aggregate([
  {
    $addFields: {
      "availableProducts": {
        $reduce: {
          input: "$availableProducts",
          initialValue: "",
          in: {
            "$cond": {
              if: {
                "$eq": [
                  {
                    "$indexOfArray": [
                      "$availableProducts",
                      "$$this"
                    ]
                  },
                  0
                ]
              },
              then: {
                "$concat": [
                  "$$value",
                  "$$this"
                ]
              },
              else: {
                "$concat": [
                  "$$value",
                  ",",
                  "$$this"
                ]
              }
            }
          }
        }
      }
    }
  },
  {$out:'collection'}
])

Use it carefully, as the $out stage will replace your entire collection with the result. My advice is to test without $out stage before.

You can test it here

Comments

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.