1

I have a collection Brands, I have to replace the path ./assets/ to D:/data/db/images , I have multiple occurrences of this in multiple documents. How do I acheive this using a query ?

Sample of each document

{"name":"Dell","images":["./assets/dell1.jpg","./assets/dell2.jpeg","./assets/dell3.jpg"],
             "captions":["Yours is here","Easy as dell","Uniquely you"],
             "logo":"./assets/dell4.png",
             "details":{"headOffice":"Bangalore","address":"No.12/1, Divyashree Green, Koramangala Inner Ring Rd, Domlur, Bengaluru - 560071",
             "phoneNumber":"(080) 28077000  ","website":"www.dell.com"}
             }
4
  • I'm sure this is not the elegant way but for small collections, we use to call mongodump, sed and mongorestore. Very easy but very sysadmin-like :-) Commented Sep 27, 2018 at 9:13
  • Please explain what you're speaking Commented Sep 27, 2018 at 11:57
  • you dump your collection as a text file with mongodumb (keep a copy of this before any other step), then you do some text substitution with sed and you re-inject the modified documents to your DB with mongorestore. If you are not on Linux you can forget that solution. If your collection contains more than 10000 entries you better forget it also. Commented Sep 27, 2018 at 12:19
  • Sorry, I did not see the D:/ in your path. You are on windows and my solution will not help. Commented Sep 27, 2018 at 12:22

1 Answer 1

2

You can use Aggregation Framework's $out operator to redirect the output of your aggregation to particular collection. If you specify the same collection name then it will replace existing collection.

To overwrite existing field you can use $addFields operator. Then you just have to remove the length of ./assets/ using $substr and concatenate that with your new prefix using $concat

db.Brands.aggregate([
    {
        $addFields: {
            images: {
                $map: {
                    input: "$images",
                    as: "image",
                    in: {
                        $concat: [ "D:/data/db/images", { $substr: [ "$$image", 8, { $strLenBytes: "$$image" } ] } ]
                    }
                }
            }
        }
    },
    { $out: "Brands" } //replaces existing collection
])

In MongoDB 3.2 you can run following script:

db.Brands.find().forEach(function(doc){
    doc.images = doc.images.map(function(image){ return image.replace("./assets/","D:/data/db/images/") })
    db.Brands.save(doc);    
})
Sign up to request clarification or add additional context in comments.

5 Comments

Unfortunately i'm using MongoDB 3.2 , is there any other workaround?
Any output you can attach ?
Please check the collection name. I've used dummy col just to test on my machine, changed to Brands in my answer
Well I had changed that before executing, it doesn't work tho
Perhaps you can create a new collection with the document from your post, run this script and check if it works (that's what I did) and then try to compare that data model with yours

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.